<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bakoulis George</title>
    <description>The latest articles on DEV Community by Bakoulis George (@bakgeorge).</description>
    <link>https://dev.to/bakgeorge</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1180779%2F754a9d1e-aa51-4e6d-a841-9ee95b8e5f4c.jpeg</url>
      <title>DEV Community: Bakoulis George</title>
      <link>https://dev.to/bakgeorge</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bakgeorge"/>
    <language>en</language>
    <item>
      <title>From Material Engineering to PHP</title>
      <dc:creator>Bakoulis George</dc:creator>
      <pubDate>Thu, 02 Apr 2026 08:55:01 +0000</pubDate>
      <link>https://dev.to/bakgeorge/from-material-engineering-to-php-4k0n</link>
      <guid>https://dev.to/bakgeorge/from-material-engineering-to-php-4k0n</guid>
      <description>&lt;p&gt;I used to work as a material engineer.&lt;/p&gt;

&lt;p&gt;My first job was helping out with stainless steel stuff. Nothing glamorous. But that's where I started, handling materials, not code.&lt;/p&gt;

&lt;p&gt;I found a payslip from that job last week, cleaning out my Google Drive. My first salary as a material engineer. I stared at it for a minute trying to remember what that person thought was going to happen next.&lt;/p&gt;

&lt;p&gt;It wasn't a plan that got me here. It was a lot of smaller things bumping into each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  The canvas problem
&lt;/h3&gt;

&lt;p&gt;The decision to move into development didn't come from an epiphany. It came from a warehouse management software I used every day at the engineering job. At some point I started wondering how it worked. That was one piece.&lt;/p&gt;

&lt;p&gt;But once I decided I wanted to be a developer, I had no idea where to start. No one to point me in a direction, just the internet and a thousand course creators with a thousand different opinions on the right approach.&lt;/p&gt;

&lt;p&gt;It felt like being handed every painting tool in the world and told to paint. The paralysis of not starting because there might be a better approach. I know people say "just start." I find that annoying, not because it's wrong, but because it's obvious and still hard.&lt;/p&gt;

&lt;h3&gt;
  
  
  The path
&lt;/h3&gt;

&lt;p&gt;I got lucky,  a support engineer role opened up at a software company. I spent two years watching how features shipped, how bugs got fixed, how developers talked to each other. I learned MySQL. Wrote small scripts. Tried to get into a software engineering program by writing code on paper. I didn't get in.&lt;/p&gt;

&lt;p&gt;Eventually the CTO gave me a shot and I got a developer role.&lt;/p&gt;

&lt;p&gt;Then I started looking for other jobs and went off the rails for a while. I was learning Python because a listing looked interesting. Doing LeetCode questions that had nothing to do with my actual work. Applying for roles I had no experience for. Months of that. Eventually I stopped and went back to PHP.&lt;/p&gt;

&lt;p&gt;I've written about this before, the "running before walking" part. For years it was just learning as fast as I could in whatever direction felt urgent. It mostly didn't work.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it actually was
&lt;/h3&gt;

&lt;p&gt;I just changed careers. It took six years and a lot of wrong turns, but that's roughly what it is. &lt;/p&gt;

&lt;p&gt;What I have now that I didn't have before is a direction that doesn't feel like a sprint. A small startup, Laravel and Vue.js. For the first time I'm not learning to keep up. I'm just learning. My day-to-day has much less stress even though I still spend most evenings and weekends reading and writing code.&lt;/p&gt;

&lt;p&gt;If you're in the middle of your own messy pivot, I don't have advice. I just know that the clean version of the story doesn't exist. Not mine, not yours. You just keep going until the thing you're doing starts to feel like the thing you should be doing.&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>php</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What I Found Inside Eloquent's increment()</title>
      <dc:creator>Bakoulis George</dc:creator>
      <pubDate>Thu, 02 Apr 2026 08:34:27 +0000</pubDate>
      <link>https://dev.to/bakgeorge/what-i-found-inside-eloquents-increment-dkk</link>
      <guid>https://dev.to/bakgeorge/what-i-found-inside-eloquents-increment-dkk</guid>
      <description>&lt;p&gt;I was experimenting with &lt;code&gt;firstOrNew()&lt;/code&gt; and &lt;code&gt;increment()&lt;/code&gt; in my Laravel lab and ended up running a query I did not expect.&lt;/p&gt;

&lt;p&gt;I was building a small inventory tracker to see how these two methods interact. The idea is that when a shipment comes in, find the product and bump its stock count. If it doesn't exist yet, a new record gets created first. &lt;code&gt;firstOrNew()&lt;/code&gt; seemed like the right tool, one call, handles both cases.&lt;/p&gt;

&lt;p&gt;If you've ever used these two together, this is worth knowing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$incomingShipment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$inventoryItem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;firstOrNew&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Metallic Coffee Mug'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$incomingShipment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stock_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Metallic Coffee Mug" wasn't in the database. So &lt;code&gt;firstOrNew()&lt;/code&gt; returned a new unsaved model instance — no &lt;code&gt;id&lt;/code&gt;, no primary key, and &lt;code&gt;$model-&amp;gt;exists = false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then I called &lt;code&gt;increment()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the query log showed
&lt;/h3&gt;

&lt;p&gt;I had three items in the table going in:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;product_name&lt;/th&gt;
&lt;th&gt;stock_count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macbook air M4&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELL monitor&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Varmilo Keyboard&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After &lt;code&gt;increment('stock_count', 50)&lt;/code&gt;, every single row got updated:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;product_name&lt;/th&gt;
&lt;th&gt;stock_count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macbook air M4&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELL monitor&lt;/td&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Varmilo Keyboard&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No error. No warning. The Coffee Mug still doesn't exist — &lt;code&gt;increment()&lt;/code&gt; doesn't insert.&lt;/p&gt;

&lt;h3&gt;
  
  
  How increment() actually works
&lt;/h3&gt;

&lt;p&gt;Digging into the source, &lt;code&gt;increment()&lt;/code&gt; internally calls &lt;code&gt;incrementOrDecrement()&lt;/code&gt;, which checks &lt;code&gt;$this-&amp;gt;exists&lt;/code&gt; before building the query.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;exists = false&lt;/code&gt; the model hasn't been saved yet — it runs the UPDATE without a WHERE clause. The whole table gets hit.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;exists = true&lt;/code&gt;, it scopes the query to the model's primary key. That's what you'd normally expect.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;firstOrNew()&lt;/code&gt; when it finds nothing returns an unsaved model. So &lt;code&gt;exists&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, and &lt;code&gt;increment()&lt;/code&gt; takes the unscoped path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using these two together correctly
&lt;/h3&gt;

&lt;p&gt;Once you know what &lt;code&gt;exists&lt;/code&gt; does, the behaviour makes complete sense. The fix is to make sure the model is persisted before you call &lt;code&gt;increment()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$incomingShipment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$inventoryItem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;firstOrNew&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Metallic Coffee Mug'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;$incomingShipment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$incomingShipment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;stock_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$incomingShipment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$incomingShipment&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'stock_count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use &lt;code&gt;firstOrCreate()&lt;/code&gt; instead, it persists the record immediately, so &lt;code&gt;increment()&lt;/code&gt; always has an &lt;code&gt;id&lt;/code&gt; to scope to.&lt;/p&gt;

&lt;p&gt;The more I dig into Eloquent's internals, the more I see how consistently it's designed around the &lt;code&gt;exists&lt;/code&gt; flag. It's a small property that a lot of methods quietly depend on.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>eloquent</category>
      <category>database</category>
    </item>
    <item>
      <title>What $with Does to Your Queries in Laravel</title>
      <dc:creator>Bakoulis George</dc:creator>
      <pubDate>Thu, 26 Mar 2026 08:47:46 +0000</pubDate>
      <link>https://dev.to/bakgeorge/what-with-does-to-your-queries-in-laravel-2fj7</link>
      <guid>https://dev.to/bakgeorge/what-with-does-to-your-queries-in-laravel-2fj7</guid>
      <description>&lt;p&gt;If you use &lt;code&gt;$with&lt;/code&gt; on your Eloquent models, you might be running more queries than you think.&lt;/p&gt;

&lt;p&gt;I stumbled upon &lt;code&gt;protected $with = ['modelA', 'modelB']&lt;/code&gt; a few months back in an application that was experiencing slow page loads. I set up a dummy blog in my local Laravel Lab (laralab.test) to experiment with it. What I found was that &lt;code&gt;$with&lt;/code&gt; cascades, and one query can quietly become five.&lt;/p&gt;

&lt;p&gt;Here's the setup. We have two simple emtpy models, "Author" and "Category", and the rest are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Comment&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$with&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BelongsTo&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BelongsTo&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$with&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BelongsTo&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Author&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BelongsTo&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;HasMany&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Laravel's default User model.&lt;/p&gt;

&lt;p&gt;Notice the &lt;code&gt;$with&lt;/code&gt; property on both Comment and Post. That's where things get interesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Without &lt;code&gt;$with&lt;/code&gt;: 1 query
&lt;/h3&gt;

&lt;p&gt;I commented out &lt;code&gt;protected $with = ['post', 'author']&lt;/code&gt; in the Comment model and requested the 10 latest comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/test-with-cascade'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;enableQueryLog&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;Comment&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;getQueryLog&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"comments"&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;"created_at"&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt; &lt;span class="k"&gt;limit&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One query. Clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  With &lt;code&gt;$with&lt;/code&gt;: 5 queries
&lt;/h3&gt;

&lt;p&gt;I uncommented the &lt;code&gt;$with&lt;/code&gt; property and ran the same route. Instead of 1 query, there were now 5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"comments"&lt;/span&gt; &lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;"created_at"&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt; &lt;span class="k"&gt;limit&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"posts"&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="nv"&gt;"posts"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"authors"&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="nv"&gt;"authors"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"categories"&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="nv"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;"authors"&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="nv"&gt;"authors"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1 query became 5.&lt;/strong&gt; Same route, same data, same code, the only difference is that &lt;code&gt;$with&lt;/code&gt; property.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cascade: &lt;code&gt;$with&lt;/code&gt; triggers &lt;code&gt;$with&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What happened is that I told Laravel: every time you load a Comment, also load its Post and Author. But the Post model also has &lt;code&gt;$with = ['author', 'category']&lt;/code&gt;. So loading those posts triggers the same process again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load Post's author:
&lt;code&gt;select * from "authors" where "authors"."id" in (1, 2, 3, 4)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Load Post's category:
&lt;code&gt;select * from "categories" where "categories"."id" in (1, 2, 3, 4)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;$with&lt;/code&gt; property cascades through your model relationships. Every model it touches checks for its own &lt;code&gt;$with&lt;/code&gt; and fires more queries.&lt;/p&gt;

&lt;p&gt;I still don't have a good use case for &lt;code&gt;$with&lt;/code&gt; on the model. Until I find one, I'm keeping it empty and loading relationships explicitly with &lt;code&gt;-&amp;gt;with()&lt;/code&gt; on the query where I actually need them.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>eloquent</category>
      <category>database</category>
    </item>
    <item>
      <title>An Open Source Project to Explore Your Internet Connection Data.</title>
      <dc:creator>Bakoulis George</dc:creator>
      <pubDate>Mon, 09 Oct 2023 14:52:45 +0000</pubDate>
      <link>https://dev.to/bakgeorge/an-open-source-project-to-explore-your-internet-connection-data-3e45</link>
      <guid>https://dev.to/bakgeorge/an-open-source-project-to-explore-your-internet-connection-data-3e45</guid>
      <description>&lt;p&gt;I wanted to understand the data I send and receive when I connect to a router.&lt;/p&gt;

&lt;p&gt;Like most people, I’ve used Speedtest by Ookla. As you know the result contains just basic information about your internet connection. But luckily they have a CLI, providing much more data.&lt;/p&gt;

&lt;p&gt;When I ran ‘speedtest’ for the first time in my terminal, I thought I must do a project with all the generated data.&lt;br&gt;
That’s how I ended up making &lt;a href="https://github.com/bak-george/WebSpeedReport" rel="noopener noreferrer"&gt;WebSpeedReport&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  WebspeedReport in a nutshell
&lt;/h2&gt;

&lt;p&gt;WebSpeedReport is an open-source software that wraps the command of Speedtest CLI, stores your data, and then displays them in a nice clean format.&lt;/p&gt;
&lt;h2&gt;
  
  
  The structure of the project
&lt;/h2&gt;

&lt;p&gt;The project has two very distinct parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the data and store them in a database.&lt;/li&gt;
&lt;li&gt;Depict the data to a localhost page.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the first part, I would use Symfony to get the generated data from Speedtest’s CLI and MySQL to store them.&lt;/p&gt;

&lt;p&gt;As for the second part I use PHP for the backend and TailwindCSS for manipulating the DOM.&lt;/p&gt;
&lt;h2&gt;
  
  
  Playing with Symfony PHP
&lt;/h2&gt;

&lt;p&gt;I wanted to build something with Symfony, but I had no idea where to start.&lt;/p&gt;

&lt;p&gt;After watching a course about the console package it seemed the perfect fit (I tried my best to forget about Python when I wrote this sentence). I made a speedtestCommand class that extends the Command class of Symfony, to handle the first part of the project. Within that class, there is an &lt;a href="https://github.com/bak-george/WebSpeedReport/blob/main/src/speedtestCommand.php" rel="noopener noreferrer"&gt;execute() function&lt;/a&gt; that does all the work.&lt;/p&gt;

&lt;p&gt;From executing the Speedtest command to storing the JSON files and creating the corresponding database to save the results of the speed test.&lt;/p&gt;

&lt;p&gt;I am currently reading more about the console package and the way I can utilize its capabilities to make the code cleaner.&lt;/p&gt;
&lt;h2&gt;
  
  
  Depicting the data
&lt;/h2&gt;

&lt;p&gt;The second part it’s the most important because it has to adequately answer the question:&lt;/p&gt;

&lt;p&gt;“How can I display the data as efficiently as possible?”.&lt;/p&gt;

&lt;p&gt;For the first version, I wanted to make things as simple as possible. That’s why for the time being you’ll find a dashboard with the most basic information and underneath it, a table containing all the speedtest runs you performed.&lt;/p&gt;

&lt;p&gt;If you want to load more information about each run, you can click on “Load More” and see all the details of that specific speed test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugh18y91532viw60mahc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugh18y91532viw60mahc.png" alt="WebspeedReport: Data Webpage" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  An issue I am working on
&lt;/h2&gt;

&lt;p&gt;As of this writing, to generate the data you have to manually run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd WebSpeedReport
./webspeedreport app:speedtest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you go inside the execute() function you’ll notice code for making your own cron jobs.&lt;/p&gt;

&lt;p&gt;I am currently testing the crons I’ve set up on my laptop and very soon you will be able to set your own through the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd WebSpeedReport
./webspeedreport app:speedtest daily 11:00,14:00,19:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;WebSpeedReport is my first open-source project.&lt;/p&gt;

&lt;p&gt;Having said that I’ll be more than happy to have some contributions and ideas on how I can make it better.&lt;/p&gt;

&lt;p&gt;So If you have an idea about a new feature or a part of code that can be better, you are more than welcome to share them &lt;a href="https://github.com/bak-george/WebSpeedReport" rel="noopener noreferrer"&gt;within the GitHub repository&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>symfony</category>
      <category>opensource</category>
      <category>speedtest</category>
    </item>
  </channel>
</rss>
