pilat

pilat

Member Since 2 Years Ago

Experience Points 16,160
Experience Level 4

3,840 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 138
Lessons
Completed
Best Reply Awards 0
Best Reply
Awards
  • Start Your Engines Achievement

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • First Thousand Achievement

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • One Year Member Achievement

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • Two Year Member Achievement

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • Three Year Member Achievement

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • Four Year Member Achievement

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • Five Year Member Achievement

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • School In Session Achievement

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • Welcome To The Community Achievement

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • Full Time Learner Achievement

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • Pay It Forward Achievement

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • Subscriber Achievement

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • Lifer Achievement

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • Laracasts Evangelist Achievement

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • Chatty Cathy Achievement

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • Laracasts Veteran Achievement

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • Ten Thousand Strong Achievement

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • Laracasts Master Achievement

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • Laracasts Tutor Achievement

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • Laracasts Sensei Achievement

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • Top 50 Achievement

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

22 May
3 weeks ago

pilat left a reply on Feature Tests Do Not Work (404)

@DEVFREY - > You don't need the /public at the end :)

Sorry, this didn't help.

@diegoaurino

The test suite will not understand that it needs to follow this long path ( http://MYSITE_REPLACED.info/back/public/ ) to hit the API endpoints

Ae you saying there is no way, as long as my Laravel application is acessed in a subfoler of site? Ok, I think I can live with that. Just wanted a confirmation.

16 May
1 month ago

pilat left a reply on Feature Tests Do Not Work (404)

But I have that public folder in the URLs I open in browser and or in the HTTPie command (http --json POST http://MYSITE_REPLACED.info/back/public/api/vote)

It's a shared hosting at the moment, and application path is like: ~/sitename/public_html/back/ and the web-path is "/back/public".

15 May
1 month ago

pilat left a reply on Feature Tests Do Not Work (404)

Couple more things:

phpunit.xml

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>

        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
    </php>
</phpunit>

.env.testing:

APP_DEBUG=true
APP_URL=http://MYSITE_REPLACED.info/back/public

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=<SAME_AS_LIVE_APP>
DB_USERNAME=<SAME_AS_LIVE_APP>
DB_PASSWORD=<SAME_AS_LIVE_APP>

(note: the problem was the same before I even created this .env.testing)

pilat started a new conversation Feature Tests Do Not Work (404)

Hi, I'm having this little (I'm sure) problem with testing, but I seem to be stuck as I don't know how to troubleshoot it further. There just seem to be not enough info…

Here's the test (simplified):

    /**
     * A basic feature test example.
     *
     * @return void
     */
    public function testUserCanVote()
    {
        $this->withoutExceptionHandling();

        $postData = [/* ... */]; // fill in some data;

        $response = $this->postJson('api/vote', $postData);
    }

Here's the response:

$ php7.2 ./vendor/bin/phpunit tests/Feature/VoteTest.php
PHPUnit 7.5.8 by Sebastian Bergmann and contributors.

Time: 171 ms, Memory: 16.00 MB

There was 1 error:

1) Tests\Feature\VoteTest::testUserCanVote
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: POST http://MYSITE_REPLACED.info/back/public/api/vote

.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithExceptionHandling.php:118
.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:326
.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:120
.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:347
.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:319
.../public_html/back/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:210
.../public_html/back/tests/Feature/VoteTest.php:51

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.

Notes:

Laravel 5.8.

10 May
1 month ago

pilat left a reply on How To Work On Different Version Of Laravel?

Concerning the upgrade itself: I personally have found the following way is the most "thorough":

  1. Do it one version at a time. I.e., 5.3 to 5.4, then 5.4 to 5.5 and so on.

  2. Bring over all the changes from github's comparison tool. Example: https://github.com/laravel/laravel/compare/5.3...5.4 (then switch to File changes tool). Usually, this covers majority of changes.

  3. Go through "Upgrade guide" to find any changes you'd like to bring over to your client code (such as Cache now uses number of seconds instead of minutes and etc — you'll not catch those via github comparison tool)

  4. Go through "What's new in Laravel v5.{target}" videos — there were, actually, couple of points those videos brought to my attentions that I haven't caught through previous steps.

pilat left a reply on How To Work On Different Version Of Laravel?

@THEMCCALLISTER - Thnk you. At the very moment I've almost finished the upgrade (remaing changes are updating client code that uses guzzlehttp/guzzle and maatwebsite/excel libs, as they have received major updates). However, I still need to switch back and forth.

So, currently I'm trying an approach with having two separate directories: in one I'm in the master, in anther — I'm int the e `upgr branch. I'll try to report if there are any drawbacks.

07 May
1 month ago

pilat started a new conversation How To Work On Different Version Of Laravel?

Hi, I have Laravel 5.3 project locally.

There is also upgrade to Laravel 5.8 in progress.

When I do the upgrade, I switch to upgrade branch, when I have to hit-fix anything in current version — I switch back to o `mas.

The problem is: I need to re-build all dependencies (composer + npm) every time I switch between branches, because both those folders are not in the CVS.

How does anyone addresses this problem?

15 Jan
5 months ago

pilat started a new conversation Caching Responses On Specific URLs

Hi, is there a way to cache JSON responses on selected routes/URLs?

Say, /api/account/some-id — return it from cache unless it is 5+ minutes old.

Preferably, if the cached resource can be returned without even hitting PHP.

Even more preferably, if I could setup this via .htaccess =)))

07 Jan
5 months ago

pilat left a reply on Coding Efficient Jobs

@MARTINBEAN - Well, what I'm asking is that people share their experience. Someone's tired those "various tools" to profile mem leaks" and have already found out that tools A, D and G are better suited for laravel jobs inspection.

Someone has already stumbled upon some certain errors that are only "visible" in such jobs, but not in "one-shot" scripts.

etc.

pilat started a new conversation Coding Efficient Jobs

Recently, I've moved from queue:listen to queue:work, because the project consumes lots of resources on doing its main job (like syncing between external API and local DB, processing webhooks, many scheduled tasks), so, spending even more resources on bootstrapping… I don't know.

The "hacky" point, however, is that daemonized daemon may leak memory. So, my questions is: how do I make sure that the memory is not leaked in my jobs?

  • How can I detect a memory is leaked (without horizon; I'm on Laravel 5.3 now)
  • What should I care about, when writing jobs? Should I explicitly close DB connection, for instance? Or, does Laravel do it for me? Should I close cache file's handlers (I'm using CACHE_DRIVER=file) manually? etc.
  • Is there a good guide on how to write Laravel jobs specifically for daemon runner?

2nd point: I'm also thinking about all that "full-blooded boots" when the only thing, that is expected from controller — is dispatching a job (e.g., processing a webhook). Maybe, there's a solution to put a new job into queue (I'm using DB driver for jobs) without loading Laravel? I'm thinking of a stand-alone PHP script with very little footprint here.

06 Jan
5 months ago

pilat left a reply on Setting Wait_timeout For MySQL Connection

@THECODEMILL - Have to revisit this question for the same reason. I have some routes that do not need to consult database while service (the data is taken from cache, etc.) and having this DB::statement() in the AppSerivceProvider forces the DB connection to be established regardless…

30 Dec
5 months ago

pilat left a reply on Queue Solution For Shared Hosting

@DAEM0N - I have a question: how does it play with other scheduled (not queued) tasks? I mean, won't this command take all time to execute and other's won't simply have a chance? Or, will others be processed just on the next minute's execution, because of that withoutOverlapping()?

pilat left a reply on Queue Solution For Shared Hosting

@DIEGOPONCIANO - Turns out that flock is only good for preventing from running the same command more than once. What it doesn't:

  1. it won't register if a listener has hung up (i.e., it's still in ps axf, but the queue is not moving)
  2. it does not guarantee removing lock file after process has finished; so, next time it wont start…

Discovered it recently — it looks that something's changed on the server and now they kill listeners quite often…

21 Nov
6 months ago

pilat left a reply on Performant Way To Mass "update Or Create"

@KFIRBA - Recently, I've got huuuge (naturally, 3 levels of magnitude) speedup with this "fix":

        - DB::statement($query, $params); // this one took around 30 seconds
        
        + $stmt = DB::getPdo()->prepare($query);
        + $success = $stmt->execute($params); // this one takes 31.45ms (magnitude of three!)

There are downsides, of cause:

  • query is not registered in Debugbar
  • no automatic type conversion (you have to check for types to match in the client code, when preparing "params" array)

But, maybe, has a sense to enable this as an option ($unsafeButFast = false) =)

pilat left a reply on Database Queue On Shared Hosting

Regarding the command: here's the lates "edition", which I haven't changed for the last year, maybe… See that it has `- and `arguments now.

flock -xn /tmp/laravel_queues.lockfile -c "/usr/bin/php /path/to/laravel/artisan queue:listen"

This revision did not pose any issues that I know of.

pilat left a reply on Casting To Boolean

@WILK_RANDALL - My bad, checked on wrong model… Yes, it passes strict comparison, which is exactly what's expected :-)

22 Oct
7 months ago

pilat left a reply on Minimal Bootstrap For Webhooks Processing

Both the Jobs are queued. So, the controller's job is only to receive the webhook, analyse it a little bit (reject 'leads.update' ones; find if there is a custom job available) and dispatch queued jobs. The dispatched jobs are then executed in a separate thread/process (in a worker).

Overall, the server is pretty loaded, yes. But… I think that upgrading hardware is not a proper way to solve this certain issue :-) There is no heavy-loading at all, in this specific action: as it only needs to add a record to "jobs" table and immediately response with 200 - Ok status. Just wondering if I really need to load "bootstrap whole laravel application" for doing so…

pilat started a new conversation Minimal Bootstrap For Webhooks Processing

Hi,

Is there a way to load "as less Laravel as possible" when processing a webhook? The objective here is to send the response asap otherwise the external system would send the same webhook again and eventually would disable webhooks at all.

Note: I'm using queued jobs already, so my controller looks like this:

class WebhooksController extends Controller
{
    public function process(Request $request)
    {
        if ($request->has('leads.update')) {
            // do not process this kind of hooks…
            return response("Ok", 200);
        }

        try {
            // Cache-related routines:
            $job = new \App\Jobs\UpdateLeadJob($request->all());
            $this->dispatch($job);
        } catch (\Exception $e) {
            Log::critical("[webhooks] dispatching primary job failed: {$e->getMessage()}", $request->all());
        }

        try {
            // Custom webhook processors:
            $customJob = $this->getCustomJob($request);
            if ($customJob) {
                $this->dispatch($customJob);
            }
        } catch (\Exception $e) {
            Log::critical("[webhooks] dispatching custom job failed: {$e->getMessage()}", $request->all());
        }

        $executionTime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
        if (1.9 < $executionTime) {
            Log::error("[webhooks] webhook processing took more than 2 secs!", $request->all());
        }

        return response("Ok", 200);
    }

    // ...

}

Still, it happens sometimes that it's not fast enough. So, I can usually see several "webhook processing took more than 2 sec" messages in the logs.

So, probably I need a way to disable middlewares or something else… Is there any way to reduce the application loading time?

13 Oct
8 months ago

pilat left a reply on Performant Way To Mass "update Or Create"

Well, this worked for some time, but now it hit its top as well…

After some good chunk of "thinking time", I've realised that I'm willingly making the system overly complicated on low [!!and, what's most important — not well-learned!!] level (Database) for the sake of simplicity on high-level (ORM). This is just wrong…

What I do: I regularly sync (and less often, but still regularly, re-sync from scratch) data from an external API into my application's database, so that I could query this data as I need. And for "closer" access, for sure.

Thus, here's my basic conditions:

  1. Lots of writes; Often, in large chunks (could easily be like a half a million records within one sync session);

  2. A need to keep IDs for existing records.

  3. At the same time, I need to remove the records not available now.

Here's the pseudo-code of how it's done now:

// 1. updating a number of leads;

$leadIds = $this->updateLeadsSince($timestamp);

// 2. now, need to update some linked data

$this->syncCustomFields( $leadIds );

// ...
protected function syncCustomFields( $leadIds )
{
    // Step 1: mark all related fields as deleted, without actually deleting them:
    
    CustomField::whereIn('lead_id', $leadIds)->update([ 'deleted' => true ]);

    // Step 2: update or insert new data, utilising "INSERT … ON DUPLICATE UPDATE";
    // all new records are written with "deleted = false";
    
    $this->generateCustomFieldsForLeads($leadIds);

    // Step 3: delete the records remaining with "deleted = true" for real:
    
    CustomField::where('deleted', true)->delete();
}

With this schema, I often get wait lock errors, especially on update([ 'deleted' => true ]) queries. The insertion itself (Step 2) is also slower than I would like… An I have no idea on how to optimise it, without giving up one any of the 'basic conditions"…

--

However.

If to look "from a bird's sight height", what I actually need in this case: is a composite primary key + REPLACE INTO statements. That's all and it's definitely simpler.

The Eloquent ORM, however, does not provide any good support for composite primary keys, and this is why I added "AUTO INCREMENTAL" surrogate key in the very beginning. But this key is causing so many troubles in unknown area now, that I'm considering to convert my tables in a way to have it simpler on the database level and tackle with Eloquent instead; This might work, for example: https://blog.maqe.com/solved-eloquent-doesnt-support-composite-primary-keys-62b740120f

So, I'll hopefully keep you informed. ;-)

22 Aug
9 months ago

pilat left a reply on Optimize MySQL To Avoid Locks

  1. I'm on a shared hosting at this moment…

  2. This is clearly an application issue. I mean, despite it can be solved by tweaking MySQL, the "for real" fix assumes doing something to the application code. Suppose, I upgrade MySQL and get rid of these deadlocks/timeouts on my current loading, but as the number of users grows, the issue would inevitably get back…

21 Aug
9 months ago

pilat started a new conversation Optimize MySQL To Avoid Locks

Hi,

Regularly get errors like this:

SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction (SQL: delete from `custom_fields` where `subdomain` = subdomain_name and `deleted` = 1)

The query may really take quite a long time (too many records in this DB table), thus there are locks… Is there a way to make it in a lockless fashion? To split onto several smaller queries or something like that?

01 Aug
10 months ago

pilat left a reply on Single-file Components: Failed To Mount Component: Template Or Render Function Not Defined.

A workaround ("kostillie"): replace all .js with .react.

mix.react('resources/assets/js/app.js', 'public/js')
   .react('resources/assets/js/map.js', 'public/js')
   .react('resources/assets/js/calendar.js', 'public/js');
   // … few more deps

pilat left a reply on Troubleshooting "Serialization Of Closure Is Not Allowed" Issue When Caching Routes

I've found a duplicate route that fixed this issue.

The error message is very misleading, I'd say…

pilat started a new conversation Single-file Components: Failed To Mount Component: Template Or Render Function Not Defined.

Hi,

I've trying to migrate from elixir to mix in my Laravel 5.3 project. What I've done so far:

  1. Rewritten package.json to be "like in laravel 5.6":
  "devDependencies": {
    "axios": "^0.18",
    "babel-preset-react": "^6.24.1",
    "bootstrap-sass": "^3.3.7",
    "cross-env": "^5.1",
    "gentelella": "^1.4.0",
    "laravel-echo": "^1.4.0",
    "laravel-mix": "^2.0",
    "laravel-vue-pagination": "^1.2.0",
    "portal-vue": "^1.3.0",
    "pusher-js": "^4.2.2",
    "vue": "^2.5.7",
    "vuedraggable": "^2.16.0"
  },

Note: I'm loading jQuery and some other "non-vue" libs from CDN, so, they're not in this list.

  1. Clean-reinstalled all dependencies: rm -rf node_modules package-lock.json && npm cache clear --force && npm install

  2. In resources/js/bootstrap.js, replaced vue-resource with axios:

window.axios = require('axios');

window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': window.Laravel.csrfToken,
    'X-Requested-With': 'XMLHttpRequest'
};

Vue.prototype.$http = axios;

  1. Added function mix(...) implementation to my app/helpers.php

  2. "converted" gulfile.js to webpack.mix.js:

let mix = require('laravel-mix');
mix.sass('resources/assets/sass/app.scss', 'public/css')
   .sass('resources/assets/sass/accounts_custom.scss', 'public/css')
   .sass('resources/assets/sass/map.scss', 'public/css')
   .sass('resources/assets/sass/calendar.scss', 'public/css');

mix.js('resources/assets/js/app.js', 'public/js')
   .js('resources/assets/js/map.js', 'public/js')
   .react('resources/assets/js/calendar.js', 'public/js');
   // … few more deps

if (mix.inProduction()) {
    mix.version();
}
  1. Built the project: npm run dev

Now, in my browser, I get errors like this in every place, where any component from .vue file is referenced:

map.js:1449 [Vue warn]: Failed to mount component: template or render function not defined.

found in

---> <Waiter> at resources/assets/js/map_components/Waiter.vue
       <Root>

, here's how this specific component is plugged in:

Vue.component('waiter', require('./map_components/Waiter.vue'));

But, the problem is the same with any component…

What am I missing?

26 Jul
10 months ago

pilat left a reply on Casting To Boolean

I'm afraid it's confusing and may lead to errors. Here's the documentation:

Now the is_admin attribute will always be cast to a boolean when you access it, even if the underlying value is stored in the database as an integer:

Ok, so I can check it like this: $user->is_admin === true?

nope.

# tinker

>>> App\Activity::first()->processed === 0
=> true

>>> App\Activity::first()->processed === false
=> false
25 Jul
10 months ago

pilat started a new conversation Troubleshooting "Serialization Of Closure Is Not Allowed" Issue When Caching Routes

I'm trying to cache routes in Laravel 5.3-based project. Here's the error I get:

$ php artisan route:cache -v

Route cache cleared!


  [Exception]
  Serialization of 'Closure' is not allowed


Exception trace:
 () at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php:95
 serialize() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php:95
 Illuminate\Foundation\Console\RouteCacheCommand->buildRouteCacheFile() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Foundation/Console/RouteCacheCommand.php:65
 Illuminate\Foundation\Console\RouteCacheCommand->fire() at n/a:n/a
 call_user_func_array() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Container/Container.php:508
 Illuminate\Container\Container->call() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Console/Command.php:169
 Illuminate\Console\Command->execute() at /Users/pilat/version-control/mappanel/vendor/symfony/console/Command/Command.php:261
 Symfony\Component\Console\Command\Command->run() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Console/Command.php:155
 Illuminate\Console\Command->run() at /Users/pilat/version-control/mappanel/vendor/symfony/console/Application.php:817
 Symfony\Component\Console\Application->doRunCommand() at /Users/pilat/version-control/mappanel/vendor/symfony/console/Application.php:185
 Symfony\Component\Console\Application->doRun() at /Users/pilat/version-control/mappanel/vendor/symfony/console/Application.php:116
 Symfony\Component\Console\Application->run() at /Users/pilat/version-control/mappanel/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:121
 Illuminate\Foundation\Console\Kernel->handle() at /Users/pilat/version-control/mappanel/artisan:35

Important notes:

  • I've already moved all Closures from route/*.php files to controllers and re-checked it several times. The only closures in these files remaining are in Route::group constructions.
  • I've tried a script like this, jut to be on the safe side (it returned nothing):
# tinker

$routes = app('router')->getRoutes()

foreach ($routes as $route) {
    if (is_object($route) && ($route instanceof Closure)) {
        $r = new ReflectionFunction($route);
        dump($r->getFilename());
    }
}
10 Jul
11 months ago

pilat left a reply on Show Uncaught Exceptions To Console Rather Than Laravel.log File

here's for 5.4: https://gist.github.com/adamwathan/125847c7e3f16b88fa33a9f8b42333da

But it worked for 5.3 as well (copied only the interesting pieces over, not the whole php file).

05 Jul
11 months ago

pilat left a reply on Valet, Custom Driver With Other PHP Version

@willvincent I like your idea of switching between installed phps, but it doesn't work for some reason…

Here's my aliases:

# PHP versions
alias use56="brew unlink [email protected] && brew unlink php && brew link --force [email protected] && valet restart"
alias use70="brew unlink [email protected] && brew unlink php && brew link --force [email protected] && valet restart"
alias use72="brew unlink [email protected] && brew unlink [email protected] && brew link php && valet restart"

And here's the result of using one of them:

✗ use56
Unlinking /usr/local/Cellar/[email protected]/7.0.30_1... 0 symlinks removed
Unlinking /usr/local/Cellar/php/7.2.7... 0 symlinks removed
Warning: [email protected] is keg-only and must be linked with --force
Note that doing so can interfere with building software.

If you need to have this software first in your PATH instead consider running:
  echo 'export PATH="/usr/local/opt/[email protected]/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/[email protected]/sbin:$PATH"' >> ~/.zshrc

In Brew.php line 182:

  Unable to determine linked PHP.


restart

Could you help me to get this working?

30 Jun
11 months ago

pilat left a reply on How Do I Get List Of All Available Attributes In The Model?

It looks I can do i this way:

return array_key_exists($key, $this->attributes) || $this->hasGetMutator($key));

Let me test it out :-)

pilat started a new conversation How Do I Get List Of All Available Attributes In The Model?

Hi,

What I need is to get a list of all available attributes (keys) on the model, including accessors.

Here's what I'm trying to do:

public function fillData($template)
{
    preg_match_all('/{([^}]+)}/', $template, $matches);
    $placeholders = $matches[1];

    $attributes = $this->getFullAttributesList(); // <<< HOW??

    $replaceData = [];

    foreach ($placeholders as $placeholder) {
    if (in_array($placehoder, $attribute)) {
        $replaceData[$placeholder] = $this->{$attribute};
        }
    }

    return $this->miniTwig($template, $replaceData);
}

protected function miniTwig($template, $data)
{
    $what = array_map(function ($key) {
        return '{' . $key . '}';
    }, array_keys($data));

    $with = array_values($data);

    return str_replace($what, $with, $template);
}


protected function getFullAttributesList()
{
    // is there a way?
}


/// Useage exmaple:

$model->fillData("The product {product_name} costs {price");
09 Apr
1 year ago

pilat started a new conversation How To Receive And Process Request Known To Be In Non UTF-8 Charset?

Hi,

Here's the issue: one of sites sends data to my app in a non-UTF-8 charset. That site is not under my control, so, let I it be as it is.

Now, when I'm trying to process this data, I have few issues.

  1. I cannot log the request data.
Log::debug("[[email protected]{$site}] request", [ $request->all() ]);

Log::debug("[[email protected]{$site}] request", [ $_REQUEST ]);

Both lines produce the following in the log file:

[2018-04-09 15:40:05] production.DEBUG: [[email protected]] request

(there's not even "[]" after the "message" part and it's strange…)

  1. Later on, when I try to dispatch a Job with this data as payload, I get the following error:

[2018-04-09 15:40:06] production.ERROR: exception 'InvalidArgumentException' with message 'Unable to create payload: Malformed UTF-8 characters, possibly incorrectly encoded' in /home/i/ivento/kartazamerov.ru/public_html/mappanel/vendor/laravel/framework/src/Illuminate/Queue/Queue.php:94

  1. Error stays the same even if I try to covert this data from the original charset to UTF-8:
        $payload = $request->all();
        if ('ThatDinozaurus' === $SiteName) {
            $payload = iconv('CP1251', 'UTF-8', json_encode($payload));
            $payload = json_decode($payload, true);
        }

The task: to be able to handle those requests as well as other, good'ol utf-8 ones. I know which site sends non-standard charset. I have iconv at my disposal. But still something's wrong…

27 Feb
1 year ago

pilat left a reply on Can I Cancel Event Broadcasting From Within The Event Class?

Okey, I'll stick with helpers, again =)

  1. Make a helper function. E.g., this one:
function pusher($event) // @tido find better name with lower risk of collision
{
    if (is_null($event->broadcastOn())) {
        return;
    }

    event($event);
}
  1. In the Event class, you can make all the checks in ::broadcastOn() and return null if it shouldn't be published:
class SomethingWasSynced implements ShouldBroadcast
{

    // ...

    public function broadcastOn()
    {
        if (! $this->broadcastWhen()) {
            return null;
        }

        return new Channel("syncing-{$this->subdomain}");
    }

    public function broadcastWhen() // if I ever upgrade to 5.6+, I'll leave this method as is, but remove that check from `::broadcastOn()` ;-)
    {
        if (App::runningInConsole())
            return false;
        }

        return true;
    }
}
  1. Use pusher() instead of event() in your client code:
pusher(new SomethingWasSynced($this->subdomain, 'custom_fields', $count));
26 Feb
1 year ago

pilat left a reply on Can I Cancel Event Broadcasting From Within The Event Class?

@mrbadr doesn't work.

I've tried:

  1. Returning null from __construct();
  2. Returning null from broadcastOn();

Having BROADCAST_DRIVER=log in the .env file, I can see that broadcasting is still happening:

[2018-02-26 17:56:37] local.INFO: Broadcasting [App\Events\SomethingWasSynced] on channels [] with payload:
{
    "broadcastQueue": "pusher",
    "subdomain": "domain1",
    "what": "activities",
    "totalCount": 40,
    "socket": null
}

Just the list of channels is empty. I am wondering: will these messages (with the empty list of channels) be actually sent to Pusher and eat up my notifications limits?

pilat left a reply on Can I Cancel Event Broadcasting From Within The Event Class?

The second question is: how do I tell a web request (Http\Kernel) from a Console one (Console\Kernel)? Can I do it from within the event class as well?

It seems I can use this guy: App::runningInConsole()

pilat left a reply on Can I Cancel Event Broadcasting From Within The Event Class?

UPDATE: I've just found broadcastWhen() method in the documentation for Laravel 5.6, but there is no such method in Laravel 5.3. So, need to find the other way around.

pilat started a new conversation Can I Cancel Event Broadcasting From Within The Event Class?

Hi, I have an event class to send notifications about external API sync status. It's quite simple, and I'm appending the code to the end of this post.

Now, I have one task: I'd only like to broadcast this event if the following conditions are both met:

  1. It's not Local environment;
  2. t is Http kernel, not Console (because the syncing can also be initiated as Artisan command or a scheduled task and there is no use for websockets in this case).

Now, I'm using something like this in my "client code" when firing the event:

        if (! App::environment('local')) {
            event(new SomethingWasSynced($this->subdomain, 'custom_fields', $this->cfsGeneratedCount));
        }

The problem: I have to remember to use this conditions every time I need to fire this event. Besides, it's not very dry this way.

So the question is: can I check this condition and cancel/abort broadcasting from within the event itself? For example, by returning false in constructor or calling some magic method, I don't know…

The second question is: how do I tell a web request (Http\Kernel) from a Console one (Console\Kernel)? Can I do it from within the event class as well?

class SomethingWasSynced implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;

    /**
     * The name of the queue on which to place the event.
     *
     * @var string
     */
    public $broadcastQueue = 'pusher';

    public $subdomain;
    public $what;
    public $totalCount;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($subdomain, $what, $totalCount)
    {
        $this->subdomain = $subdomain;
        $this->what = $what;
        $this->totalCount = $totalCount;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new Channel("syncing-{$this->subdomain}");
    }

    public function onQueue()
    {
        return 'pusher';
    }
}
17 Jan
1 year ago

pilat left a reply on Search In JSON Column Does Not Work With Query Builder And Eloquent Model (but Works With Raw Query)

I've found the issue. Hope, it may help someone:

It turns out that linked_company_id is stored as string in the json structure I search in. Like: …,"linked_company_id":"68743242",…n't ask me why, I get this data from external service's API). So, I've tried the following code:

$allLeadsEloquent = LeadsCache::where('json->linked_company_id', (string)$companyId)
    ->get();

And it worked.

Still, I find it not very neat, for at least the following reasons:

  1. How come the Debugbar still produces the query that actually finds rows?

  2. This "strict type match" is quite hard to debug. Especially, considering that type match is not required when searching in normal (not JSON) column.

pilat started a new conversation Search In JSON Column Does Not Work With Query Builder And Eloquent Model (but Works With Raw Query)

Hi, in Laravel 5.3, I'm trying to use that short syntax for the JSON columns:

$allLeadsEloquent = LeadsCache::where('json->linked_company_id', $companyId)
    ->get();

The result is: empty collection. Note: the same result is with Query Builder (DB('table_name')).

Now. I open Debugbar and grab the "Raw query" produced by this code and run this query in the Sequel Pro: there it finds some rows!

Here's the how the raw query looks:

select * from `leads_cache` where `json`->'$."linked_company_id"' = '68743242'

What possibly could go wrong with this?…

11 Jan
1 year ago

pilat left a reply on Performant Way To Mass "update Or Create"

@kfirba

Finally implemented this approach and had some time to test it out. Looks good so far! At least, I can be sure that relations records IDs stay unchanged (once created) and they're not going to overflow INTEGER type eventually :-)

Thank you very much!

pilat left a reply on How To Make Sure/check If A Listener Is Not Queued?

There probably was some other error in the code, resulting in that data not to become immediately available… Don't remember how I've fixed it, to be honest, but the issue is not there anymore.

pilat left a reply on Disabling Vue Devtools In Production

I'm not sure if I want to create Webpack config specifically for this one option (I have Laravel 5.3). Will these options work "runtime"? I mean, if I do the following in my app.js file:

if (location.hostname.indexOf('production-domain.com') === -1) {
    Vue.config.debug = true;
} else {
    Vue.config.devtools = false;
    Vue.config.debug = false;
    Vue.config.silent = true;
}
10 Jan
1 year ago

pilat started a new conversation Setting Wait_timeout For MySQL Connection

Hi, I need to set wait_timeout session variable for the database connection. BUt:

  1. It has to be done inside my application because the hosting team refuses to change this option "for all of the users". They say I can do it easily by issuing the following query: SET SESSION wait_timeout = XXXXXX.

  2. I need to find a proper place in which to issue this query. As I understand, it should be issued somewhere near connection establishing, is it right? There is no such option in config/database.php and I shouldn't touch files inside vendor/, off cause. Besides, this adjustment should be indexed by git.

So, could you advise a proper way to inject this?

13 Dec
1 year ago

pilat left a reply on Is There A Nice Way To Handle Empty Dates In Templates?

One more question: is there a way to extend Carbon\Carbon in a way, that all Eloquent models would use my custom class for the dates? Meanwhile, I shall probably issue a feature request to Carbon themselves…

12 Dec
1 year ago

pilat left a reply on Is There A Nice Way To Handle Empty Dates In Templates?

There's no evaluation going on except for the PHP interpreter.

I don't now… I'm literally parsing $input into arguments.

If that bothers you then you should probably stop using Blade. The whole thing is based on it.

I see. Let us put it this way: I don't trust myself writing this kind of code. I'm ok with built-in directives, written by masters and covered by loads of tests ;-) I'd better use helper function for this one case.

@tykus: optional() is a thing! I should probably backport this helper into my Laravel 5.3. based project. If I need some fallback text, should I use it Like this?

{{ optional($record->some_date_field)->format('d.m.Y') or 'n/a' }}

pilat left a reply on Is There A Nice Way To Handle Empty Dates In Templates?

@topvillas Blade extension looks like a plan!

But… Here's what I came to:


// AppServiceProvider.php

// ...
       Blade::directive('dateOrText', function ($input) {
            $args = preg_split('/\s*,\s*/', $input);
            $expression = $args[0];
            $defaultText = isset($args[1]) ? $args[1] : "'-'";
            $format = empty($args[2]) ? "'d.m.Y'" : $args[2];

            return "<?php echo date_or_text($expression, $defaultText, $format); ?>";
        });
// ...

// helpers.php

// ...
function date_or_text($expression, $defaultText = '-', $format = 'd.m.Y')
{
    if (is_numeric($expression)) { // timestamp is passed:
        if (0 === $expression) {
            return $defaultText;
        }
        $expression = \Carbon\Carbon::createFromTimestamp($expression);
    }

    // assume that DateTime object is passed:
    return (int)$expression->format('Y') > 1970 ? $expression->format($format) : $defaultText;
}

// template.blade.php

                <td>
                    @dateOrText($task->complete_till_carbon, '-', 'd.m.Y H:i')<br>
                    @dateOrText($task->complete_till, '-', 'd.m.Y H:i')<br>
                    @dateOrText($task->complete_till, '-')<br>
                </td>

… but the question: is `@dateOrText(…argooking so much better than an `{{ date_or_text(…argshat it worth parsing sing ` in the the `Blade::dir's callback? Besides, the whole hole `Blade::direc concept smells like like ` to me…

So, the final version:

// helpers.php

// ...
function date_or_text($expression, $defaultText = '-', $format = 'd.m.Y')
{
    if (is_numeric($expression)) { // timestamp is passed:
        if (0 === $expression) {
            return $defaultText;
        }
        $expression = \Carbon\Carbon::createFromTimestamp($expression);
    }

    // assume that DateTime object is passed:
    return (int)$expression->format('Y') > 1970 ? $expression->format($format) : $defaultText;
}

// template.blade.php

                <td>{{ date_or_text($task->complete_till_carbon, '-', 'd.m.Y H:i') }}</td>

pilat started a new conversation Is There A Nice Way To Handle Empty Dates In Templates?

Hi,

Let say, I have a nullable Date or DateTime field in my DB. Eloquent exports it to templates as Carbon object, so, I can freely setup formatting:

<td>{{ $record->some_date_field->format('d.m.Y') }}</td>

This is very convenient, and I'd prefer to have this option available.

The problem is when 'm trying to display dates from those records, that have it empty (or null; or zero, if I store timestamps). Here's a piece of real code:

    public function getCompleteTillCarbonAttribute()
    {
        return \Carbon\Carbon::createFromTimestamp($this->complete_till);
    }
<td>{{ $task->complete_till_carbon->format('Y-m-d') }}</td>

When original complete_till is 0, I'll have 1970-01-01 date on the output. To avoid this, I should do one of the following:

  1. Use conditions in blade:
<td>{{ 0 === $task->complete_till ? 'n/a' : $task->complete_till_carbon->format('Y-m-d') }}</td>
  1. Make a function that returns date as string:
    public function getCompleteTillStringAttribute()
    {
    return 0 === $this->complete_till
        ? 'n/a'
        : date('d.m.Y', $this->complete_till); // don't see any use for Carbon in this case
    }

Neither way is very elegant, I wold say. I'd prefer to control the template to be in charge for appearance, but not to have that ugly ternary condition operator…

Something like this: {{ $record->a_date->format('d.m.Y')->ifEmpty('n/a') }}, or this: {{ $record->a_date->format('d.m.Y', 'n/a') }};

Do anyone have good solution to the issue?

27 Nov
1 year ago

pilat left a reply on Eager Load Relations Stored In Json Field

I'm on the same issue too. Here's my example:

# Eloquent model:
class Activity extends Model
{
    // ...
    public function notifications()
    {
        return $this->hasMany(\App\NotifyLog::class, 'report->activity->element_id', 'element_id');
    }
    // ...
}


# Client code:
# 1. No eager loading:
App\Entities\Activity::has('notifications')->take(3)->get()->map(function ($a) { return $a->notifications; });
# ^^^ works like a charm.

# 2. With eager loading:
App\Entities\Activity::with->('notifications')->has('notifications')->take(3)->get()->map(function ($a) { return $a->notifications; });
# ^^^ nope… Here's the exact results:
# "select * from `activities` where exists (select * from `notify_logs` where `notify_logs`.`report`->'$."activity"."element_id"' = `activities`.`element_id`) limit 3"
# []
# 17504.04
# "select * from `notify_logs` where `notify_logs`.`report`->'$."activity"."element_id"' in (?, ?)"
# array:2 [
#   0 => 15062832
#   1 => 13737651
# ]
# 1.27
# => Illuminate\Support\Collection {#1114
#      all: [
#        Illuminate\Database\Eloquent\Collection {#1085
#          all: [],
#        },
#        Illuminate\Database\Eloquent\Collection {#1087
#          all: [],
#        },
#        Illuminate\Database\Eloquent\Collection {#1061
#          all: [],
#        },
#      ],
#    }

pilat left a reply on With() Does Not Work If I Use Where() In Relations

Ok. What I understand at this moment is that there has to be an option to use ::withColumn() in the eager-loading query builder.

Something like this:

    public function custom_fields()
    {
        return $this->hasMany(\App\CustomField::class, 'element_id', 'element_id')
            ->whereColumn('custom_fields.subdomain', 'activities.subdomain');
            // or simpler: ->whereColumn('subdomain', 'subdomain');
    }

    public function lead()
    {
        return $this->hasOne(\App\AmoLeadsCache::class, 'id', 'element_id')
             ->whereColumn('leads_cache.subdomain', 'activities.subdomain');
    }
    // this doesn't work, off cause…

At the moment, I'll stick to the custom made local scopes, like this one:

    public function scopeWithLead($query, $subdomain)
    {
        return $query
            ->with([ 'lead' => function ($query) use ($subdomain) {
                $query
                    ->where('subdomain', $subdomain);
            }]);
    }

, although I don't find it very DRY having to repeat that $subdomain constraint on both the Activitiy and its relations:

// finally, the client code:
\App\Entities\Activity::subdomain('subdomain1')->withLead('subdomain1')->take(3)->get();
// don't like that repetition of subdomain constraint however… :/
22 Nov
1 year ago

pilat left a reply on With() Does Not Work If I Use Where() In Relations

@BryceSharp thank you. It looks similar to my current workaround.

However, I loose eager loading this way. So, if I have, say, 500 activities in the list, I'll execute 500 extra SQL queries to fill them all.

You are assuming that the instance of Activity calling fillData() has the scope of the eager loaded lead.

Yes, this is what bothering me. Why is it exactyl there is no that scope when I use ->where() in the relation functions, but the scope is present when I don't use ->where()? Is there a way I could preserve both the extra constraint in relations AND the eager loading?