rodrigo.pedra

rodrigo.pedra

Lead Developer at avaliadora.com.br

Member Since 5 Years Ago

São Carlos, Brazil

Experience Points
163,740
Total
Experience

1,260 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
762
Lessons
Completed
Best Reply Awards
127
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 33
163,740 XP
Jan
15
1 week ago
Activity icon

Awarded Best Reply on Transaction Helper

I use a middleware for that:

<?php

namespace App\Http\Middleware;

use Closure;
use Exception;
use Illuminate\Database\ConnectionInterface;
use Symfony\Component\HttpFoundation\Response;

class DbTransaction
{
    /** @var \Illuminate\Database\ConnectionInterface */
    private $connection;

    public function __construct(ConnectionInterface $connection)
    {
        $this->connection = $connection;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     * @throws \Throwable
     */
    public function handle($request, Closure $next)
    {
        $this->connection->beginTransaction();

        try {
            $response = $next($request);
        } catch (Exception $exception) {
            $this->connection->rollBack();
            throw $exception;
        }

        if ($response instanceof Response && $response->getStatusCode() > 399) {
            $this->connection->rollBack();
        } else {
            $this->connection->commit();
        }

        return $response;
    }
}

Add this you controller constructor:

namespace App\Http\Controllers;

use App\Http\Middleware\DbTransaction;

class MyController extends Controller
{
    public function __construct()
    {
        $this->middleware(DbTransaction::class)->only(['store']);
    }

    // ... controller methods
}

Here I am using the middleware class directly in the controller's constructor, but you can add it to app/Http/Kernel.php with an alias and use the alias.

Dec
02
1 month ago
Activity icon

Awarded Best Reply on GET IMAGE ETAG VALUE IN S3 BUCKET USING LARAVEL

Guzzle is a HTTP client implemented in PHP. So you can make requests to other servers from your PHP code:

http://docs.guzzlephp.org/en/stable/

If you never used it and find it a bit cumbersome you can try using Zttp which is a simple wrapper around Guzzle:

https://github.com/kitetail/zttp/

I actually don't manage the etag myself. I know it is generally used to improve browser cache for static assets (images, css, etc.), but I use the defaults from S3 or CloudFront.

Just mentioned because you asked how to "Get image etag value in S3 bucket using Laravel".

Dec
01
1 month ago
Activity icon

Replied to Laravel Foreign Key Drop-down List In Blade

Youre welcome! Glad to help =)

Activity icon

Awarded Best Reply on Laravel Foreign Key Drop-down List In Blade

It seems you are missing one argument when passing your data into the view.

public function create()
{
    $cabletyps = Cabletyp::pluck('cabletypscol', 'idcabletyps');

    // missing the with argument
    return view('cablename.create')->with('cabletyps', $cabletips);
}

If it still doesn't work, try removing the cast to array from the @foreach call.

<div class="col-md-12">
    <div class="form-group">
        <strong>cabletyp_id</strong>
        <select name="cabletyp_id" class="form-control" required>
            <option value=""> -- Select One --</option>
            @foreach($cabletyps as $cabletyp)
                <option value="{{ $cabletyp->idcabletyps }}">
                    {{ $cabletyp->cabletypscol }}
                </option>
            @endforeach
        </select>
    </div>
</div>
Nov
30
1 month ago
Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

Hi @jgravois

Saw this article on twitter about upgrading PHP versions on a Mac. Also tells how to update valet.

https://stitcher.io/blog/php-74-upgrade-mac

Maybe there is something in it that can help you

Nov
29
1 month ago
Activity icon

Awarded Best Reply on How To Gracefully Quit A Job Being Handled By Queue?

I usually just return;. The queue manager does not care with what the job returns. It will just report with it throws an exception.

As long you don't throw an exception you can early return if you don't need the job to run anymore.

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

Sorry, am out of ideas... =(

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

After "sourcing" can you run PHP?

$ php -v

If it still doesn't work, try closing and reopening your terminal to "force-source".

The weirdest thing is that by your code the "composer global..." ran, which should be using the installed PHP version.

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

Oh, one more thing.

If you don't need multiple PHP versions installed, try removing the old ones.

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

So maybe php-fpm for php 7.3 is missing in your system.

As I am not a macOS user, I found this article:

https://panlw.github.io/15274361469556.html

Most of the steps you already have done. But this one caught my attention:

  brew tap homebrew/dupes && \
  brew tap homebrew/php && \
  brew install --without-apache --with-fpm --with-mysql php70

I guess you'd need to run somthing similar to the last line:

  brew install --without-apache --with-fpm --with-mysql php

So it gets the right modules. Take this advice with care, I am not familiar with brew. Do some research on how you can install missing PHP extensions through brew.

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

Well the error changed a bit, now it complains about not finding this file: /usr/local/etc/php/7.3/php-fpm.d/www.conf

Check if it exists:

$ ls /usr/local/etc/php/7.3/php-fpm.d/www.conf

If it does not exist, check you PHP version:

$ php -v

If you have more than one PHP version installed that might be the problem. In Linux I change the default version using the update-alternatives command, but don't know if that is possible with macOS.

Either way if the . conf file mentioned above does not exist in your system you might need to reinstall PHP.

===

Note: I saw you uninstalled php (brew uninstall php70) and then reinstalled with a different package name (brew install php) .

Do you know if this command brew install php installs both PHP CLI and PHP-FPM (which is used by nginx and valet to handle web requests)?

In Ubuntu I need to install both packages

$ sudo apt install php7.3 php7.3-fpm

Maybe you need to manually install the PHP-FPM from brew

Activity icon

Replied to How To Get Best Sellers Of Ecommerce?

It seems you are missing the group by clauses. When using an aggregate column you should group your results.

Check this Laracasts video on SQL Aggregates:

https://laracasts.com/series/mysql-database-design/episodes/6

Try this simplified version and see if it works:

Route::get('best', function () {
    $products = Product::query()
        ->join('order_items', 'order_items.productId', '=', 'products.id')
        ->selectRaw('products.*, SUM(order_items.quantity) AS quantity_sold')
        ->groupBy(['products.id']) // should group by primary key
        ->orderByDesc('quantity_sold')
        ->take(20) // 20 best-selling products
        ->get();

    return $products;
});

Tested locally, with a slightly different DB model, and it worked. You may have to change something to get ir working with your DB structure.

Hope it helps.

Activity icon

Replied to Valet Is Broken And Won't Let Me Reinstall

Couple of things you can try:

  1. Clear composer cache

    $ composer clear-cache
    
  2. Remove any valet global files from composer

    $ rm -rf ~/.config/composer/vendor/laravel/valet
    

Note I am in linux so your composer global path might be different. If you don't know where the global composer folder is located try running

$ composer global update

And hit CTRL+C to stop the update. The first line in the output must be something like:

Changed current directory to /home/rodrigo/.config/composer

That is where your composer global files are located.

One alternative to manually removing the valet files would be trying to remove it globally:

$ composer global remove laravel/valet

Hope any of this helps you.

Activity icon

Replied to Laravel-medialibrary - Serialization Of 'Closure' Is Not Allowed

From the flareapp stack trace it seems the problem comes from storing the user model into the session.

Why do you need to store an unsaved user model into the session?

And how is media library going to return a media file to a model that is not saved into the database?

I didnt dig into the code to check the problem, but my guess from previous usage is this:

  1. When you call getFirstMedia, as the user instance is not saved, the media library might been returning a closure to resolve it later
  2. As the session is serialized after the request is sent to the browser, when Laravel tries to serialize the user model it fails on serializing the closure set on the previous step.

Cant test right now as I am on the phone, but hope it can give you some insights to fix this issue

Activity icon

Replied to Need Help, Password Protect A Page Or Resource Route

If it is a single route I would use a custom FormRequest with the authorization on its authorize method.

https://laravel.com/docs/6.x/validation#authorizing-form-requests

You can return an empty array on the rules method as it doesn't need to validate anything.

For a route group a Middleware is a better option.

Activity icon

Replied to Can I Send An Email Without A Database / User From The Database?

Great you find a solution, but just to add to your initial question, I use the Mail façade to send to a e-mail like this:

    public function __invoke(SendEmailRequest $request, Estimate $estimate)
    {
        Mail::to($request->input('email'))->send(new SendEstimate($estimate));

        return Response::noContent();
    }

And it works.

A thought it would work with an array because of the code int the [email protected] from the core.

But...

After inspecting the core code, the Mail façade uses the `Maile class to build the e-mail. And that class (after proxing thorugh the `PendingMai class) call the `[email protected] with only one argument.

So for setting both name and email you should use an array of arrays:

Mail::to([
    [ 'name' => 'Joe Schmoe', 'email' => '[email protected]' ],
])->send(new ContactForm());

And it should work.

Activity icon

Replied to Can I Send An Email Without A Database / User From The Database?

Change address to email and it should work

        Mail::to(
            [
                'name' => 'Joe Schmoe',    
                'email' => '[email protected]'
            ]
        )->send(new ContactForm());
Activity icon

Replied to Laravel Foreign Key Drop-down List In Blade

It seems you are missing one argument when passing your data into the view.

public function create()
{
    $cabletyps = Cabletyp::pluck('cabletypscol', 'idcabletyps');

    // missing the with argument
    return view('cablename.create')->with('cabletyps', $cabletips);
}

If it still doesn't work, try removing the cast to array from the @foreach call.

<div class="col-md-12">
    <div class="form-group">
        <strong>cabletyp_id</strong>
        <select name="cabletyp_id" class="form-control" required>
            <option value=""> -- Select One --</option>
            @foreach($cabletyps as $cabletyp)
                <option value="{{ $cabletyp->idcabletyps }}">
                    {{ $cabletyp->cabletypscol }}
                </option>
            @endforeach
        </select>
    </div>
</div>
Activity icon

Replied to How To Gracefully Quit A Job Being Handled By Queue?

I usually just return;. The queue manager does not care with what the job returns. It will just report with it throws an exception.

As long you don't throw an exception you can early return if you don't need the job to run anymore.

Activity icon

Awarded Best Reply on Get PDF File From Url

Try this:


Route::get('download', function () {
   $url = 'https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=5223955&DocType=Customer+Drawing&DocLang=English';

   // Create a stream
   $opts = [
       "http" => [
           "method" => "GET",
           "header" => "Host: www.te.com\r\n"
               . "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0\r\n"
               . "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
               . "Accept-Language: en-US,en;q=0.5\r\n"
               . "Accept-Encoding: gzip, deflate, br\r\n"
       ],
   ];

   $context = stream_context_create($opts);
   $data = file_get_contents($url, false, $context);

   \Storage::disk('public')->put('filename.pdf', $data);

   return 'OK';
});
Activity icon

Replied to Get PDF File From Url

Try this:


Route::get('download', function () {
   $url = 'https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=5223955&DocType=Customer+Drawing&DocLang=English';

   // Create a stream
   $opts = [
       "http" => [
           "method" => "GET",
           "header" => "Host: www.te.com\r\n"
               . "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:71.0) Gecko/20100101 Firefox/71.0\r\n"
               . "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
               . "Accept-Language: en-US,en;q=0.5\r\n"
               . "Accept-Encoding: gzip, deflate, br\r\n"
       ],
   ];

   $context = stream_context_create($opts);
   $data = file_get_contents($url, false, $context);

   \Storage::disk('public')->put('filename.pdf', $data);

   return 'OK';
});
Activity icon

Replied to Get PDF File From Url

In this SO answer there are other approaches you can try:

https://stackoverflow.com/a/724449/1211472

Check if your php.ini has allow_url_fopen=true

At last resource you could try a PHP HTTP Client such as Guzzle or Symfony HTTP Client, but both will rely on techniques described in the link above.

Activity icon

Replied to Get PDF File From Url

Try this:

$contents = file_get_contents('https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=5223955&DocType=Customer+Drawing&DocLang=English');

\Storage::disk('public')->put('filename.pdf', $contents);
  1. it will save to storage/app/public
  2. run php artisan storage:link to create an alias in the public folder
Activity icon

Replied to Split Webpack Bundles By Param

Nice approach, great you found a solution.

I generally don't reach for dynamic imports as most of the projects I work on are internal tools at business with few modules, so loading everything is not a pain and support for old browsers is required. But I'll definitely look for using them more.

Didn't know output folder for chunks was configurable (at least from Laravel mix), I guess this was one of the reasons I skipped using dynamic imports as it seemed to clutter the public folder a lot.

Thanks for the insights and Happy Thanksgiving.

Activity icon

Awarded Best Reply on How To Add Input Field Using JS ?

Give this a try:

<!DOCTYPE html>
<html lang="en-US">
<head>
    <title>jQuery Dynamic Form</title>

    <script crossorigin="anonymous" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<h1>My Form</h1>
<form id="my-form" action="/your-action-here">
    <div class="fields"></div>

    <p>
        <button type="button" class="add-fields">
            Add fields
        </button>

        <button type="submit">
            Send form
        </button>
    </p>
</form>

<!--
    text/x-templates is a fake type  just to tell
   the browser to ignore this script block
-->
<script type="text/x-templates" id="fields-templates">
    <p class="input-fields">
        <input name="title[]" placeholder="title">
        <input name="description[]" placeholder="description">
        <button type="button" class="remove-fields">
            Remove these fields
        </button>
    </p>
</script>

<script>
$(function () {
    var FIELDS_TEMPLATE = $('#fields-templates').text();
    var $form = $('#my-form');
    var $fields = $form.find('.fields');

    $form.on('click', '.add-fields', function () {
        $fields.prepend($(FIELDS_TEMPLATE));
    });

    $form.on('click', '.remove-fields', function (event) {
        $(event.target).closest('.input-fields').remove();
    });
});
</script>
</body>
</html>

The trick here is to use a delegate on the event listener.

Nov
28
1 month ago
Activity icon

Awarded Best Reply on What Is The Best Way To Handle An App That Has Tests, Questions, Answers And The Solution To That Answere

Ok, letś try to break things up.

First, in this snippet:

// duplicated to showcase options
$user = User::with(['tests.questions.answers', 'answers.question.test']])
    ->find($userId);

$tests = $user->tests;
$answers = $user->answers;

In the comment above I suggested you to use one or other form, not both at the same time. So you should use:

$user = User::with(['tests.questions.answers'])->find($userId);

$tests = $user->tests;

To eager load first the user's tests with their associated questions and answers, if you prefer to iterate from the tests and then show each test structure.

Or:

$user = User::with(['answers.question.test']])->find($userId);

$answers = $user->answers;

And get every user's answers and have for each answer their associated question and test so you can iterate from it.

Both approaches are useful depending on what you want to display/calculate. But I guess the first one would be more usual as you would can show each test structure regardless of their answers quantity.

===

Second, regarding the suggestion to change the pivot table to a Solution model.

From what I understood, you have a table structure like this:

tests ---> questions ---> answers ---> users_tests_answers <--- users

Where and arrow (--->) represents a one-to-many relation on the arrow's direction.

So effectively the users_tests_answers is a pivot table between the answers table and the users table.

But also it is a pivot table between the tests table and users table as it also have a prueba_id column.

Internally Laravel uses the class Illuminate\Database\Eloquent\Relations\Pivot table when retrieving pivot table records in a belongs to many relation.

The Pivot class extends the Illuminate\Database\Eloquent\Model class and adds some extra methods useful for managing records from a table like that. So each pivot record, after retrieval is effectively an Eloquent Model instance.

Laravel let you customize which class you want to use for pivot records. So in this relation definition:

// app/User.php
public function tests()
{
    returh $this->belongsToMany(Test::class, 'users_tests_answers', 'user_id', 'prueba_id')
        ->using(Solution::class)
        ->as('solution')
        ->withPivot(['respuesta_id', 'respuesta_text', 'activo', /* ... */]);
}

We are saying to Laravel:

  1. Hey Laravel create a many-to-many relation between the User and Test models using the table users_tests_answers as the pivot table (first line: ->belongsToMany(...))
  2. Instead of using the regular Pivot table you generally use, please use this custom class I called Solution when hydrating the pivot records (second line: ->using(...))
  3. Also please call this relation solution instead of pivot (third line: ->as(...))
  4. And finally get these columns from the pivot table in addition to those you already select to make the join (fourth line: ->withPivot(...))

So when Laravel eagers load this relation:

$user = User::with(['tests'])->first();

For each Test instance in the user tests relation, the instance will have a solution relation automatically loaded and instantiated as an instance of the Solution class.

foreach($user->tests as $test) {
    // $test is an Test instance

    // $solution is a Solution instance
    $solution = $test->solution;
}

As Solution extends Pivot

class Solution extends Pivot {...}

And Pivot is basically an Eloquent Model, we can define relationships, accessors, mutators, anything a model would have there.

Finally this line:

foreach($user->tests as $test) {
    $answer = $test->solution->answer;
}

Is (lazy) loading the answer from a record on the users_tests_answers table.

Hope I could make things clearer.

Activity icon

Awarded Best Reply on How To Redirect A !auth-user To A Specific Route (middleware)?

The logic to handle authentication redirection is located in the Authenticate middleware, located in your project's app/Http/Middleware.

You should change line 18 in this file:

https://github.com/laravel/laravel/blob/master/app/Http/Middleware/Authenticate.php#L18

To return an URL to the desired route where to redirect a guest user. By the default it redirects to a named route with name login. If you are not using the default auth scaffolding you can manually change this file for something you are using, for example:

        if (! $request->expectsJson()) {
            return url('/login');
        }
Activity icon

Replied to Baffled!! Email Not Being Sent To To Address

Try:

Mail::to($dev->user)
    ->bcc("[email protected]")
    ->send(new DeviceOffline($dev));

Which driver are you using?

How do you know e-mail gets sent to "[email protected]" ?

Try sending to a raw e-mail and see if it works:

Mail::to("[email protected]")
    ->bcc("[email protected]")
    ->send(new DeviceOffline($dev));

If it works maybe the user's email is rejecting the e-mail (marking as spam, mailbox full, etc.)

Activity icon

Replied to Passing Data From Controller To Vue

Try this:

Change const to var:

<script>
    var user = {!! json_encode($user) !!};
    var courses = {!! json_encode($courses) !!};
    var myClasses = {!! json_encode($myClasses) !!};
    var locations = {!! json_encode($locations) !!};
    </script>

var will add the variables to the window object.

Change the mounted hook to look in the window object:

this.courses = window.courses;
this.myClasses = window.myClasses;
this.locations = window.locations;
this.notification = window.notification;
Activity icon

Replied to Laravel Passport ( Client Of Non Object) Problem

Did your run this comand:

php artisan passport:install

This command will create the default passport clients. You need a personal access client required when generating a token like the snippet you posted.

Read more in the docs.

https://laravel.com/docs/6.x/passport#installation

https://laravel.com/docs/6.x/passport#personal-access-tokens

Remember, as the clients are just records in the database you should run the command above, or create a custom personal access client, in every installation of your project, such as new dev machine or production server.

Activity icon

Replied to How To Redirect A !auth-user To A Specific Route (middleware)?

The logic to handle authentication redirection is located in the Authenticate middleware, located in your project's app/Http/Middleware.

You should change line 18 in this file:

https://github.com/laravel/laravel/blob/master/app/Http/Middleware/Authenticate.php#L18

To return an URL to the desired route where to redirect a guest user. By the default it redirects to a named route with name login. If you are not using the default auth scaffolding you can manually change this file for something you are using, for example:

        if (! $request->expectsJson()) {
            return url('/login');
        }
Activity icon

Replied to Baffled!! Email Not Being Sent To To Address

What e-mail driver are you using?

And can you past the content of the DeviceOffline mailable? If you are overriding the ->to() inside it might be what is causing this issue.

Activity icon

Replied to Addressing The Root Folder

Just tested locally and it worked:

Install package:

$ npm install froala-editor

Add to webpack.mix.js

mix.copy( 'node_modules/froala-editor/css/froala_editor.pkgd.min.css', 'public/vendor/froala-editor/css/froala_editor.pkgd.min.css' );

mix.copy( 'node_modules/froala-editor/js/froala_editor.pkgd.min.js', 'public/vendor/froala-editor/js/froala_editor.pkgd.min.js' );

compile:

$ npm run dev

verify copied:

$ ls public/vendor/froala-editor/css
froala_editor.pkgd.min.css

$ ls public/vendor/froala-editor/js
froala_editor.pkgd.min.js

verify available:

$ php artisan serve
Laravel development server started: http://127.0.0.1:8000

# in other terminal

$ wget http://127.0.0.1:8000/vendor/froala-editor/css/froala_editor.pkgd.min.css
--2019-11-28 13:34:24--  http://127.0.0.1:8000/vendor/froala-editor/css/froala_editor.pkgd.min.css
Connecting to 127.0.0.1:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 78330 (76K) [text/css]
Saving to: ‘froala_editor.pkgd.min.css’

froala_editor.pkgd.min.css                      100%[=================>]  76.49K  --.-KB/s    in 0s      

2019-11-28 13:34:24 (823 MB/s) - ‘froala_editor.pkgd.min.css’ saved [78330/78330]


$ wget http://127.0.0.1:8000/vendor/froala-editor/js/froala_editor.pkgd.min.js
--2019-11-28 13:34:40--  http://127.0.0.1:8000/vendor/froala-editor/js/froala_editor.pkgd.min.js
Connecting to 127.0.0.1:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 651274 (636K) [application/javascript]
Saving to: ‘froala_editor.pkgd.min.js’

froala_editor.pkgd.min.js                       100%[=================>] 636.01K  --.-KB/s    in 0.001s  

2019-11-28 13:34:40 (736 MB/s) - ‘froala_editor.pkgd.min.js’ saved [651274/651274]

Maybe it is difference of versions, here are my installed versions:

$ node -v
v10.16.0

$ npm -v
6.9.0

$ npm list froala-editor
/home/rodrigo/code/laravel
└── [email protected] 

$ npm list laravel-mix
/home/rodrigo/code/laravel
└── [email protected] 
Activity icon

Replied to Addressing The Root Folder

Weird... I use this in a project to copy a datatables localization json file. You don't need to create the folders beforehand, mix should create them for you.

Went to Laravel mix docs to double-check if something was wrong and the example in the docs is essentially the same:

https://laravel-mix.com/docs/5.0/copying-files

Should work or at least mix should give an error.

Try changing the destination location just to check if mix is copying the file, something like:

mix.copy( 'node_modules/froala-editor/js/froala_editor.pkgd.min.js', 'storage/app/froala-editor/js/froala_editor.pkgd.min.js' );

Then try searching for the filename with you OS (Windows Explorer, Finder, etc.) To see if the file was copied somewhere else. If that is the case there might be a configuration problem.

Activity icon

Replied to Urgent Help Needed On Laravel Forge

Weird, Rebooting should definitely clear opcache status.

Laravel does some caching in production if you run php artisan optimize or some of the cache commands.

I don't if you tried any of these, but these are some steps you could try:

  1. Remove any .php file from the prioject's /bootstrap/cache/ folder
  2. Run php artisan optimize:clear
  3. Run php artisan config:clear
  4. Run php artisan route:clear
  5. Run php artisan view:clear
  6. Check if there are any remaining compiled view in the storage/framework/views folder (remove any .php files there)

Steps 3, 4, 5 should be run as part of step 2. I listed them individually as the optimize:clear command was introduced in a recent Laravel version and I don't know which version you are using.

Step 6 should be done automatically by step 5. Listed here so if after running step 5 there are still compiled view files in the storage/framework/views you should check if your folder permissions are configured properly. (maybe after migrating versions something happen).

Those are what I could think your Laravel app itself could be retaining as cache.

If you already tried those steps and it still didn't work there could be a nginx configuration problem (you should update your nginx conf to delegate to the new php-fpm version) but I would assume you either migrated through forge panel (which update these files automatically) or already have checked the .conf file for each site you have in your forge server.

Hope something here can help you.

Nov
27
2 months ago
Activity icon

Replied to Addressing The Root Folder

You cannot reference a file outside the public folder directly.

You can try some options:

  1. Copy the files to the public folder
  2. Expose (stream/download) the files the files through a route
  3. Create a symlink to the files you need to the public folder

I definitely would not do through option3 as it is the less maintainable (you'll have to recreate the symlinks when deploying or changing servers or dev machine).

Option 2 is reasonable if you are not expecting a lot of access, but it is essentially bad as you are consuming server ressources for a task it can do automatically.

Option 1 at first seems a bad alternative as you might think you would loose the ability to have updated files whenever you update your npm dependencies. But you can automate this copy with Laravel Mix:

mix.copy( 'node_modules/froala-editor/css/froala_editor.pkgd.min.css', 'public/vendor/froala-editor/css/froala_editor.pkgd.min.css' );

mix.copy( 'node_modules/froala-editor/js/froala_editor.pkgd.min.js', 'public/vendor/froala-editor/js/froala_editor.pkgd.min.js' );

The after building your mix assets you can reference them like this:

<link href="{{ asset('vendor/froala-editor/css/froala_editor.pkgd.min.css') }}" rel="stylesheet" />

<script src="{{ asset('vendor/froala-editor/js/froala_editor.pkgd.min.js') }}"></script>
Activity icon

Replied to Addressing The Root Folder

I don't quite understand your request... which links are you referring to?

Either way, if you want to read a file from the base path you can use the base_path helper:

$path = base_path('node_modules/path/to/file');

Note that it will generate an absolute path and not an URL.

Nov
26
2 months ago
Activity icon

Replied to What Is The Best Way To Handle An App That Has Tests, Questions, Answers And The Solution To That Answere

Ok, letś try to break things up.

First, in this snippet:

// duplicated to showcase options
$user = User::with(['tests.questions.answers', 'answers.question.test']])
    ->find($userId);

$tests = $user->tests;
$answers = $user->answers;

In the comment above I suggested you to use one or other form, not both at the same time. So you should use:

$user = User::with(['tests.questions.answers'])->find($userId);

$tests = $user->tests;

To eager load first the user's tests with their associated questions and answers, if you prefer to iterate from the tests and then show each test structure.

Or:

$user = User::with(['answers.question.test']])->find($userId);

$answers = $user->answers;

And get every user's answers and have for each answer their associated question and test so you can iterate from it.

Both approaches are useful depending on what you want to display/calculate. But I guess the first one would be more usual as you would can show each test structure regardless of their answers quantity.

===

Second, regarding the suggestion to change the pivot table to a Solution model.

From what I understood, you have a table structure like this:

tests ---> questions ---> answers ---> users_tests_answers <--- users

Where and arrow (--->) represents a one-to-many relation on the arrow's direction.

So effectively the users_tests_answers is a pivot table between the answers table and the users table.

But also it is a pivot table between the tests table and users table as it also have a prueba_id column.

Internally Laravel uses the class Illuminate\Database\Eloquent\Relations\Pivot table when retrieving pivot table records in a belongs to many relation.

The Pivot class extends the Illuminate\Database\Eloquent\Model class and adds some extra methods useful for managing records from a table like that. So each pivot record, after retrieval is effectively an Eloquent Model instance.

Laravel let you customize which class you want to use for pivot records. So in this relation definition:

// app/User.php
public function tests()
{
    returh $this->belongsToMany(Test::class, 'users_tests_answers', 'user_id', 'prueba_id')
        ->using(Solution::class)
        ->as('solution')
        ->withPivot(['respuesta_id', 'respuesta_text', 'activo', /* ... */]);
}

We are saying to Laravel:

  1. Hey Laravel create a many-to-many relation between the User and Test models using the table users_tests_answers as the pivot table (first line: ->belongsToMany(...))
  2. Instead of using the regular Pivot table you generally use, please use this custom class I called Solution when hydrating the pivot records (second line: ->using(...))
  3. Also please call this relation solution instead of pivot (third line: ->as(...))
  4. And finally get these columns from the pivot table in addition to those you already select to make the join (fourth line: ->withPivot(...))

So when Laravel eagers load this relation:

$user = User::with(['tests'])->first();

For each Test instance in the user tests relation, the instance will have a solution relation automatically loaded and instantiated as an instance of the Solution class.

foreach($user->tests as $test) {
    // $test is an Test instance

    // $solution is a Solution instance
    $solution = $test->solution;
}

As Solution extends Pivot

class Solution extends Pivot {...}

And Pivot is basically an Eloquent Model, we can define relationships, accessors, mutators, anything a model would have there.

Finally this line:

foreach($user->tests as $test) {
    $answer = $test->solution->answer;
}

Is (lazy) loading the answer from a record on the users_tests_answers table.

Hope I could make things clearer.

Activity icon

Replied to Sharing "global" Variables To Certain Urls

Great! Glad to help =)

Activity icon

Replied to Lazy Eager Loading With Condition On Current Model

Sure,if you have few books, maybe after filtering for some other field, that won't be a problem. But in general it is a good idea to avoid making a query for each model (called N+1 problem).

Activity icon

Replied to Eloquent: How To Recursively Get The Details Of The Top Of The Tree For A Given Child

Great ! Glad to help =)

One info that might help you in the future is that the order of columns on that SELECT clause matters. As the first columns (@post_id:= ...) will be executed before updating the @comment_id column.

Activity icon

Awarded Best Reply on Laravel Jobs - Execute Job At Exact Time?

I don think this is something you can achieve with exact predictability. There are several factors that could delay the job execution: Database is busy, server is running a lot of tasks at the moment, Redis is busy, network latency (if redis is in another machine), etc...

Even in JavaScript where the event-loop is buit-in in most engines and not an external dependency, setInterval or setTImeout are not guaranteed to run exactly in the scheduled time. If the main thread is busy it often wait for the thread to be available to run.

For example, run this code in your browser console:

var sample = function () {
    var start = Date.now(), finish;

    setTimeout(function () {
        var after = Date.now();
    
        console.log('scheduled', after, (after - start) / 1000);
    }, 1000);

    for (let i of Array(100000).keys()) {
        // expensive synchronous calculation
        console.log(1000 * Math.random());
    }

    finish = Date.now();

    console.log('started', start);
   
    console.log('finished', finish, (finish - start) / 1000);
}

sample();

Of course there are mission-critical applications that achieve this level of exactness, but often these applications make use of special hardware that provide the high availability they require.

If one second of delay in an hour is a business stopper for you, you could try scheduling the job 10-5 minutes before its expected schedule and in the begining of its handle method sleeping for a second or less inside a while loop until the desired time is due.

Even though I don't think you can guarantee execution in the exact second expected.

Activity icon

Awarded Best Reply on Eloquent: How To Recursively Get The Details Of The Top Of The Tree For A Given Child

One more thing.

If you want to profile theses queries in your project:

SELECT post_id
FROM (
    SELECT
        @post_id := (SELECT commentable_id FROM comments WHERE id = @comment_id and commentable_type = 'App\\Post') AS post_id,
        @comment_id := (SELECT commentable_id FROM comments WHERE id = @comment_id and commentable_type = 'App\\Comment') AS comment_id
    FROM
        comments, (SELECT @comment_id := 3500, @post_id := NULL) AS initialization
    WHERE @post_id IS NULL
) AS recurse
WHERE post_id IS NOT NULL;

Other approach:


SELECT
    commentable_id as post_id
from comments
WHERE id = (SELECT MIN(comment_id) FROM (SELECT
    @comment_id := (SELECT commentable_id FROM comments WHERE id = @comment_id and commentable_type = 'App\Comment') AS comment_id
FROM
    comments, (SELECT @comment_id := 3500, @post_id := NULL) AS initialization
WHERE @comment_id IS NOT NULL) AS recurse);

They took around 1 second to run on my machine on a comments table with about 125K records for a comment in the 20th level.

For a comment in the 5th level both queries run under 500ms.

In both scenarios the first query runs a bit faster than the second.

500ms to 1 second is a lot for user interaction, but if your need is to run in some kind of queued job or console command it might be ok depending on the frequency of those jobs/commands.

Also there might be some easy optimizations on the queries above as I am bit rust on writing this kind of queries.

Nov
25
2 months ago
Activity icon

Replied to GET IMAGE ETAG VALUE IN S3 BUCKET USING LARAVEL

Guzzle is a HTTP client implemented in PHP. So you can make requests to other servers from your PHP code:

http://docs.guzzlephp.org/en/stable/

If you never used it and find it a bit cumbersome you can try using Zttp which is a simple wrapper around Guzzle:

https://github.com/kitetail/zttp/

I actually don't manage the etag myself. I know it is generally used to improve browser cache for static assets (images, css, etc.), but I use the defaults from S3 or CloudFront.

Just mentioned because you asked how to "Get image etag value in S3 bucket using Laravel".

Activity icon

Replied to Appel à Une Fonction Membre GetClientOriginalExtension () Sur Null

From your form the name of the file field is photo and not bookcover:

<input type="file" name="photo" class="form-control" required>

So try changing this line in your controller:

$cover = $request->file('photo'); // CHANGE this

Sorry I don't speak/write french

Activity icon

Replied to GET IMAGE ETAG VALUE IN S3 BUCKET USING LARAVEL

I don think it is possible using the built-in Storage mechanism. As it internally uses the Flysytem library (https://flysystem.thephpleague.com/docs/adapter/aws-s3/) and its documentation has nothing about retrieving a file etag.

One thing you could try is getting the file URL and making a request to it with Guzzle and checking the response headers.

Might be an overhead but I can't think of any other method to do it.

Activity icon

Replied to Question About Javascript ES6 Arrow Function And Plugin

I configure it like that

    mounted() {
        this.pickerInstance = flatpickr(this.$el, {
            dateFormat: 'Y-m-d H:i:s',
            onChange: this.changed,
            onClose: this.changed,
            onValueUpdate: this.changed,
        });

        this.$once('hook:beforeDestroy', () => {
            this.pickerInstance.destroy();
            this.pickerInstance = null;
        });
    },

Where this.changed is a method defined by the Vue component. And this.pickerInstance is not defined in the data() option ar anywhere before as I don need it to be reactive.

Note that the onClosed option accepts a function or an array of functions, as I am only using one handler I use a function directly.

reference: https://flatpickr.js.org/options/

I don't know if this mismatch is by you defining the config object in the data() option. Just curious on why are doing that. Are you mutating the config dynamically? As Vue makes all properties returned by the data() option reactive it might be breaking some reference.

If you need to keep the config inside the data, you could try to bind the function to the this component to see if it solves your issue. Something like this:

data() {
    return{
                dates: '',
                config: {
                    mode: "range",
                    dateFormat: 'Y-m-d H:i:s',
                                onClose: [function(value){
                        const dateArr = value.map(date => this.formatDate(date, "Y-m-d H:i:s"));
                        console.log(dateArr);
                    }.bind(this)]  // <<< ADDED 
Activity icon

Replied to What Is The Best Way To Handle An App That Has Tests, Questions, Answers And The Solution To That Answere

Hi @dru ,

Unfortunately the hasManyThrough only works for two tables.

But as you have this users_tests_answers pivot table I guess you could fetch a user test with this relation:

// app/User.php
public function tests()
{
    returh $this->belongsToMany(Test::class, 'users_tests_answers', 'user_id', 'prueba_id');
}

public function answers()
{
    returh $this->belongsToMany(Answer::class, 'users_tests_answers', 'user_id', 'respuesta_id');
}

Note: If your models are named Prueba and Respuesta and not Test and Answer you can omit the last 2 parameters for each ->belongsToMany(...) calls.

So you could get a user's test like this:

// duplicated to showcase options
$user = User::with(['tests.questions.answers', 'answers.question.test']])
    ->find($userId);

$tests = $user->tests;
$answers = $user->answers;

I understand you might want the solutions as well with the answers.

I would add a Solution model and rename that users_tests_answers to solutions, as it already has an id and created_at and updated_at columns (fecha_creacion / fecha_update)

You can even extend the Pivot class and not the Model if you want:

class Solution extends Pivot {
   public $incrementing = true;

   public function user() {
       return $this->belongsTo(User::class, 'usuario_id');
   }

   public function test() {
       return $this->belongsTo(Test::class, 'prueba_id');
   }

   public function answer() {
       return $this->belongsTo(Answer::class, 'respuesta_id');
   }
}

And so in your User model you would have:

// app/User.php
public function tests()
{
    returh $this->belongsToMany(Test::class, 'users_tests_answers', 'user_id', 'prueba_id')
        ->using(Solution::class)
        ->as('solution')
        // add all pivot fields not used in this relation
        ->withPivot(['respuesta_id', 'respuesta_text', 'activo', /* ... */]);
}

And have something like this:

$user->tests->solution->answer // answer from solution

Unfortunately I don't know If you can eager load pivot relations.

Hope it helps you somehow.

Activity icon

Replied to Filter Products On Subcategory

The filter in the whereHas constraint will apply the filter to the parent (categories) query and not to the child query (products).

You can add a fliter to a nested related model while eager loading this way:

    $categories = Category::query()
        ->with(['children' => function ($relation) {
            $relation->with(['product' => function ($relation) {
                // this will apply the filter when querying the
                // products table
                $relation->where('status', 5);
            }]);
        }])
        ->get();

Maybe for your business requirements you may use a combination of both: whereHas and eager load filtering.