Terraform your Laravel deployments

https://kbouzidi.com/img/containers/assets/terraform-your-laravel-deployments.jpeg/aede5dcfccc966770807a2c35c7ec2b5.jpeg

In this article we will use terraform to provision a lemp stack for a laravel application with all its configurations (database, php, nginx, firewall, ssl, etc).

PHP Stack Provisioning

Every PHP project you worked on has that phase when you need to deploy it to a desired environment that match the application requirement usually its a LEMP or a LAMP stack.

That may require you to install and configure all these applications on the server every time manually, which can be boring, time consuming and redundant.

Terraform-php-stack

Is a terraform project that i was working on to solve my PHP stack provisioning and configurations.

if you are dealing with that manually this will speed up your applications deployments. It can also help if you are migrating to a new server.

The good part is that you can also test it locally before deciding to run it on a production server.

I tried to make the project as user-friendly as possible, so you don’t need to know Terraform to use it.

However, I will still provide a step-by-step explanation:

  1. Installing Terraform

  2. Setup Target machine

  3. Configure terraform-php-stack

  4. Deployment

  5. Contribution

In fact terraform installation is very simple, i will only cover ubuntu/debian installation for other OS, you can check the official documentation (=>).

wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

You can use this terraform project against a fresh linux instance (vps) or a local virtual machine which is cool to test stuff before a real deployment.

For local testing i use vagrant & VirtualBox, you can use any other hypervisor.

This is my Vagrantfile :

Vagrant.configure("2") do |config|
 
  config.vm.box = "ubuntu/jammy64"
  config.vm.hostname = "kbouzidi"

  config.vm.provision "shell", inline: <<-SHELL
      apt update &&  hostname -I
     
  SHELL
 
  config.vm.network "private_network", type: "dhcp"

  config.vm.provider "virtualbox" do |vb|
   
  end
   
end

COPY SSH KEY

You need to copy your public ssh key to your target server.

ssh-copy-id user@targetIP

🚨 if you skip this probably you will be lost into a desert 🏜️

Well only if you will use vagrant with its own private key.

In this part, I will walk you through how I used this for a Laravel 10 project, and don’t worry, you don’t need to know Terraform at all.

First, you need to clone the project

git clone git@github.com:Safemood/terraform-php-stack.git

To start, you need to copy the example files to create your own configurations.

cd terraform-php-stack
cp terraform.tfvars.example terraform.tfvars

As you can see, this is the folder structure :

├── main.tf
├── modules
│   ├── install_dependencies
│   │   ├── configure.sh
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── install_node
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── install_mysql
│   │   ├── create_db.sh
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── install_nginx
│   │   ├── default.tftpl
│   │   ├── main.tf
│   │   └── variables.tf
│   ├── install_php
│   │   ├── main.tf
│   │   ├── php.ini
│   │   ├── setup.sh
│   │   └── variables.tf
│   └── setup_app
│       ├── main.tf
│		├── .env.tftpl
│       └── variables.tf
├── terraform.tfvars.example

What is important in here :

  • main.tf where we can set all the required modules.

  • modules folder where the supported modules exist.

  • terraform.tfvars where we can set our environment variables && configurations.

  • .env.tftpl the template .env file for your php project.

We will configure the whole deployment only from terraform.tfvars

ssh_host            = "target ip"
ssh_user            = "ssh user"
ssh_key             = "private_key path"
php_version         = "8.2"
webmaster_email     = "example@test.com"
mysql_root_password = "crazySecurePassword"
git_repo            = "git@github.com:laravel/laravel"
db_connexion        = "mysql"
db_host             = "localhost"
db_port             = "3306"
db_name             = "kbouzidi"
db_user             = "safemood"
db_password         = "terraform"
domain_name         = "kbouzidi.com"
app_env             = "production"
app_debug           = false
scheme              = "http"  // 'https' will auto assign ssl certificates to your domain
stack_modules       = ["dependencies", "node", "nginx", "php", "app", "mysql"] // dependencies","mysql", "nginx", "php","app" , "node"
system_dependencies = "git tmux vim zip unzip htop fail2ban"
installation_steps = [
  # Set Folder Permissions
  "sudo chgrp -R www-data storage bootstrap/cache",
  "sudo chmod -R ug+rwx storage bootstrap/cache",
  # Installation
  "composer install --optimize-autoloader --no-dev",
  "php artisan key:generate --force",
  "php artisan storage:link --force",
  "php artisan migrate --seed --force",
  "sudo php artisan optimize:clear",
  "npm install && npm run build",
  "php artisan optimize"
]

What you need to know :

stack_modules is an array of the modules that you wanna install :

  • dependencies : to install required system dependencies and make other necessary configurations.

  • php : to install php on the system with the required version “php_version“.

  • node : to install nodejs & npm on the system with the required version “node_version“.

  • nginx : to install nginx and setup an nginx web server.

  • mysql : to install and setup a mysql server and a dadicated database to your project with the required permissions.

  • app : to setup and install our application.

Some other important notes:

  • scheme : https will auto assign ssl certificates to your domain using certbot.

  • git_repo : when its a private repo, you will need to add a deploy key to your project (link).

🚨 for private github repo make sure to use deploy keys so the token has access only to the related project only.

Deployment is the simplest part; just access the ‘terraform-php-stack’ folder and hit :

terraform init // only the first time
terraform apply 
// or if you know what your doing 💥
terraform apply --auto-approve

You can see how the deployment process works in action.

As you have seen, the whole LEMP stack took only 4 minutes!

You can destroy this infrastructure with :

terraform destroy 

I created this with Laravel ❤️ in mind and i really love to expand it to be helpful for all major PHP framework and stacks, so contributions are very welcome 🤗🥰.

Just keep in mind these main points :

  • The ability to use the project without being a terraform expert.

  • Simplify the process of deploying and managing infrastructure for PHP developers using Terraform.

  • Make PHP developers happier 😁.

What i have in mind for this project:

  • Add Symfony support .

  • Add a fully docker version to provision the whole stack with containers.

  • Add support for major cloud providers (aws, google cloud, azure) to make PHP stack provisioning easier on these platforms.

I hope the information I provided was helpful. If you have any questions or need further clarification, don’t hesitate to reach out to me. I’m always open to feedback, so please feel free to share any thoughts or suggestions you may have.

You can find me on LinkedIn || Twitter || Github!

Feel free to drop by and say hello – I’m always up for meeting new people and expanding my network!😊

Laravel News Links

QR Code Generator in Laravel 10

https://harrk.dev/content/images/2023/03/QR-Code-Generator-in-Laravel-10-Tutorial.webp

In this post, we will look at generating QR codes within your Laravel applications.

First, we will need to require the simple-qrcode package that provides first-party support for Laravel. The package itself wraps the Bacon/BaconQrCode package which itself is a port of the ZXing library but for PHP.

If you wish – you may directly interact with the BaconQrCode package without using simple-qrcode. However, simple-qrcode provides a better developer experience when used with Laravel. Additionally, with out-of-the-box support for overlaying images on QR codes.

With the context blurb out of the way. Let’s dig in!

Step 1: Setting Up

Spin up a new Laravel 10 project (or step over this if you already have a project ready).

$ laravel new qrcodegenerator

Set up your database connection as per your own preference. Then install the simple-qrcode package via Composer.

$ composer require simplesoftwareio/simple-qrcode "~4"

Optional! If you want to create QR codes in .png format. You will need to install the imagick extension. In most cases, all you need to do is install via pecl with pecl install imagick. If that does not work for you, then Google is your friend here as it goes beyond the topic of this article.

Step 2: Creating The Controller

Now we need to wire up a controller and route before we can pull back a QR code in our browser.

Create a new QrCodeController.

$ php artisan make:controller QrCodeController

And then reference the controller in our routes/web.php file.

<?php

use App\Http\Controllers\QrCodeController;
use Illuminate\Support\Facades\Route;

Route::get('/', [QrCodeController::class, 'show']);

Opening up the URL in our browser gives us a blank page at this point. Also as I’m using Valet here, I only need to enter the foldername.test to view the project in my browser. Your setup may be different so you do you, whether that’s php artisan serve or something else.

A very empty page

Step 3: Generating QR Codes

At the very bare minimum, you can call the QrCode facade alongside generate with something to render. And you’ll get a QR code back.

In my QrCodeController I am creating a QR code with all the default settings with the following content “Hello, World!”.

<?php

namespace App\Http\Controllers;

use SimpleSoftwareIO\QrCode\Facades\QrCode;

class QrCodeController extends Controller
{
    public function show()
    {
        return QrCode::generate(
            'Hello, World!',
        );
    }
}

Refresh the page in the browser and…

A rendered QR code
wollah!

Step 4: Customising the Generated QR Code

Alright so how about something a little more interesting? A splash of colour? Let’s use a couple of methods that allow us to change the background colour, foreground colour, and margin.

public function show()
{
    return QrCode::size(200)
        ->backgroundColor(255, 255, 0)
        ->color(0, 0, 255)
        ->margin(1)
        ->generate(
            'Hello, World!',
        );
}

And here’s the result:

QR Code with colour

Let’s try something that makes our QR codes stand out. And I’m not talking about colours anymore.

We can actually modify the style and eye (the three corners) of the QR code. Try this out:

return QrCode::size(200)
        ->style('dot')
        ->eye('circle')
        ->color(0, 0, 255)
        ->margin(1)
        ->generate(
            'Hello, World!',
        );

Result:

QR Code with Style

Before closing this section. One more on colours: gradients.

$from = [255, 0, 0];
$to = [0, 0, 255];

return QrCode::size(200)
    ->style('dot')
    ->eye('circle')
    ->gradient($from[0], $from[1], $from[2], $to[0], $to[1], $to[2], 'diagonal')
    ->margin(1)
    ->generate(
        'Hello, World!',
    );

By specifying a from and to colour, alongside a type of gradient (vertical, horizontal, etc). You can create something really cool!

A QR Code with a gradient

Merging Images

To overlay an image in a QR code – we’ll need to change the way we do a few things.

To prepare for this I have dropped an image (twitter.jpg) in my storage/app folder. Then by calling ->merge($filepath), simple-qrcode will load that image and overlay it onto the QR code.

If you want to pull in the image data yourself, you can replace merge with mergeString. Eg: ->mergeString(Storage::get($path)).

Merging an image is only supported with png QR codes, so we need to specify the format on this, too.

public function show()
    {
        $data = QrCode::size(512)
            ->format('png')
            ->merge('/storage/app/twitter.jpg')
            ->errorCorrection('M')
            ->generate(
                'https://twitter.com/HarryKir',
            );

        return response($data)
            ->header('Content-type', 'image/png');
    }

Then the result of all this:

QR Code with Twitter Logo in Centre

You may have noticed the line in regards to errorCorrection. When we overlay an image, part of the QR code’s data becomes obscured.

By default, the errorCorrection is set to the lowest value (‘L’). If you attempt to scan your QR code like this, it’s likely that the QR code will not scan. To remedy this we adjust the errorCorrection level up a notch until our code is scannable.

The various levels are:

  • L: Low (7% correction)
  • M: Medium (15% correction)
  • Q: Quartile (25% correction)
  • H: High (30% correction)

The higher the correction level, the more “noisy” the QR code becomes. Preferably you want the lowest correction level alongside a scannable QR code for the sake of keeping up appearances.

Downloading Generated QR Codes

To return a download response, you can either store the QR code as a file and return the path with return response()->download($path); or stream the contents of the QR code without using the filesystem.

An example of using streamDownload to do this:

public function download()
{
    return response()->streamDownload(
        function () {
            echo QrCode::size(200)
                ->format('png')
                ->generate('https://harrk.dev');
        },
        'qr-code.png',
        [
            'Content-Type' => 'image/png',
        ]
    );
}

Generating QR Codes in Blade

Since we’ve been using a Facade all along, generating a QR code in Blade is as simple as repeating the above steps. Call the facade, customise as required, and call generate.

{!! QrCode::size(256)->generate('https://google.com') !!}

Or another approach, encode the data within an image tag manually. For example, if you need to change the image type for whatever reason.

<img src="data:image/png;base64, {!! base64_encode(QrCode::format('png')->size(256)->generate('https://google.com')) !!} ">

QR Code Data Types

Alright, so we’ve been using URLs in these examples. Mobile devices are clever enough to figure out how to handle these when scanned, but we can go a step further.

If you want to read the long version of this. Check out the ZXing’s Wiki page.

To summarise: simple-qrcode has a couple of helpers to specify the data the QR code will contain. You can replace the generate method with any of these.

Here are a few examples:

Email

Open a blank email addressed to “hello@example.com”.

QrCode::size(200)->email('hello@example.com');

Open an email with a predefined subject and body.

QrCode::size(200)->email('hello@example.com', 'Hello World', 'This is a test message.');

Phone Number

QrCode::size(200)->phoneNumber('555-555-5555');

SMS Text Message

Send an SMS text message to 555-555-5555 with a prewritten message, “Hi!”.

QrCode::size(200)->SMS('555-555-5555', 'Hi!');

Wi-Fi

Share Wi-Fi credentials for your visitors.

QrCode::size(200)->wiFi([
    'encryption' => 'WPA/WEP',
    'ssid' => 'SSID of the network',
    'password' => 'Password of the network',
    'hidden' => 'Whether the network is a hidden SSID or not.'
]);

Geolocation

Share a location by providing a latitude and longitude.

QrCode::size(200)->geo(51.378638, -0.100897);

Conclusion

To see more advance options for QR code customisation, refer to the documentation for simple-qrcode.

As for some real world examples of this package in action. I use simple-qrcode for generating QR codes for my QR code tracking SaaS.

QRMetric – Your Dynamic QR Code Buddy

Create Dynamic QR Codes that can be modified without requiring you to redistribute a new QR code. Can be changed any time, any place, anywhere.

Otherwise, if generating QR codes with Javascript is your thing. Consider checking out the node-qrcode library. I use this for generating QR codes on a static site, without any server involvement altogether.

Random QR Code Generator

RandomQR is a QR Code Generator for those times when you just need a random QR image and nothing more. Simple, easy, and fast.

Laravel News Links

The final trailer for ‘The Super Mario Bros. Movie’ looks more like a game than ever

http://img.youtube.com/vi/RjNcTBXTk4I/0.jpg

There was a time when movies based on video games tried to distance themselves from their source material. "This ain’t no game," bragged the poster for the 1993’s live-action Super Mario Bros. film. Times have changed: The final trailer for The Super Mario Bros. Movie by Illumination leans hard into its origins. This is absolutely a game, it says. See? Here’s a scene that looks like New Super Mario Bros. U Deluxe, and another one that looks just like Mario Kart 8 Deluxe.

If you were hoping to hear more of Chris Pratt’s Mario voice, you won’t find much new here — but the final trailer does give viewers a clear look at the tone the movie is going for. We watch Bowser list off an army of familiar video game enemies. We watch Mario and Donkey Kong use power mushrooms and fire flowers as they run through a training course that looks like a traditional Mario level. We see Mario and Peach race through a brightly rendered Rainbow Road. It looks familiar. It looks fun. And it looks like a game, but with better graphics.

That’s no surprise. According to directors Aaron Horvath and Michael Jelenic, Illumination has worked closely with Nintendo to make sure the film feels right. The directors also say that Illumination has improved its lighting and rendering technology to help push Super Mario Bros. Movie to the next level "beyond anything Illumination has ever done."

As for that Mario voice? You’ll finally be able to hear the full performance when the film hits theaters next month. The Super Mario Bros. Moviereleases on April 5, 2023.

This article originally appeared on Engadget at https://www.engadget.com/the-final-trailer-for-the-super-mario-bros-movie-looks-more-like-a-game-than-ever-231926362.html?src=rssEngadget

The Creators of Disney’s Kiff Share Their Inspirations for the New Animated Series

https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_675,pg_1,q_80,w_1200/291569868a92322d62f32999bfb7f4ed.jpg

A new buddy comedy is coming to the Disney Channel and Disney+. Inspired by animated favorites like The Simpsons and DuckTales, Kiff is a new generation’s slice-of-life series in which—surrounded by friends and family in an eccentric community—two friends find adventures just around the corner.

io9 recently sat down with Kiff creators Nic Smal and Lucy Heavens to chat about the show. It centers on a spunky squirrel protagonist and her laid-back bunny bestie Barry, and takes inspiration from the people and places Smal and Heavens encountered when they were growing up.


Best Friends Forever! | Kiff | NEW Series! | Kiff a NEW @disneychannel Cartoon

Sabina Graves, io9: I’m excited to chat with you all about Kiff. I’ve watched a few of the episodes. I think it’s so bonkers and silly. I loved it. Can you tell me a bit about the inspiration for the show, and how you all collaborated on this concept?

Heavens: Thank you! We really just wanted to do a project that we would be filled with joy to make and that we wanted to watch. We had this the sort of kernel of what Kiff was in terms of her character and her personality, and we kind of spun it out from there—we just leaned on all of our favorite people and places, and it’s a very relatable show. And yeah, it was just all things that made us laugh.

Smal: We made it to the studio and we sort of clicked on similar kind of tastes in comedy and we had fun chatting about it. And I drew Kiff, which at the time was just like a big light bulb. And we both sat there and just were like: “heheheheheh.” Just the world started showing itself to us from there. It just all spun out from Kiff.

G/O Media may get a commission

io9: That’s awesome. I love how Kiff has this really big sense of go-getter adventurer attitude, and a lot of times her imagination plays out scenarios and how she thinks it should go. It’s really cool to show audiences that things aren’t always going to go as you imagine them. What was important to you in showing your audience how to navigate life when things don’t go as planned?

Heavens: I think maybe if anything, the show is like “life doesn’t go the way that you think it will.” And it’s a kind of “know thyself” show, where you look at your behavior and what motivated you and you understand yourself a bit better.

Smal: Yeah, and even if things don’t kind of turn out or pan out exactly how you imagined it, whatever kind of twists and turns happen—if you got someone you know by your side that you care for deeply and cares for you and is nonjudgmental, just the pure friendship and support, then anything’s possible. And that’s all that really matters. You know?

io9: For sure. I think anyone could use a Barry [Kiff’s bunny bestie]. I love the the family episode where Kiff gets to be an honorary member of Barry’s family, because there’s always that funny dynamic of how your family acts one way when it’s just family, and then when guests are over, it’s kind of different…

Smal: And that that feeling going over to someone’s house for the first time for a sleepover and feeling a bit like there is a difference. What’s normal to one family might be completely, wildly, not normal to another, but it’s like, “Hey, it’s all good.”

io9: It’s like such a fun dynamic to see Kiff meld into. I also had a really good time with the road trip—it kind of gave me Fury Road, Mad Max vibes. There’s certainly pop culture touchstones that stand out, like the Kill Bill noise.

Heavens: We do love and pay homage to all things popular culture.

io9: What your first fandoms in animation, and how did they inform your career path?

Heavens: It was The Simpsons—ain’t it just the way as a millennial?

Smal: We didn’t know each other at that age, but we both were recording The Simpsons on VHS, creating our own collections.

Heavens: “Do not tape over.”

Smal: Cartoons were just something that I always felt there was a connection there, and always comedy. The afternoons just spent watching back-to-back whatever was coming on. I think animation really comes and finds you. Shows like SpongeBob SquarePants and DuckTales.

Heavens: And Animaniacs.

io9: I mean, yeah.

Heavens: We both just ate it all up. But probably in terms of sensibility, [and] in terms of what informed our sense of humor, it is probably mostly The Simpsons.

io9: The world-building of the different people in Kiff’s life definitely has that [Simpsons] feel, like they each have a sense of their own inner life. When it came to creating that, were the voices for these characters on the page, or did you open it up to some of the voice talent to really make it their own as well?

Heavens: It’s a kind of endless feedback loop, where we started with the voice on the page, and then we were getting it back, and then you write more for that voice, and then there are elements that you really enjoy—and on it goes. That’s been a very happy part of the process.


Kiff premieres Friday, March 10, on the Disney Channel (8:00 p.m. EST/PST), and will drop on on Disney+ streaming right after.


Want more io9 news? Check out when to expect the latest Marvel, Star Wars, and Star Trek releases, what’s next for the DC Universe on film and TV, and everything you need to know about the future of Doctor Who.

Gizmodo

Plastic Cup Machine

http://img.youtube.com/vi/amlg8O6YS4g/0.jpg

Plastic Cup Machine

Link

Disposable plastic cups aren’t exactly the best thing for the environment. Still, it’s interesting to see how they’re made. This factory machine takes rolls of plastic and uses a vacuum and heat to thermoform thousands of cups an hour. After it spits out cups, spinning brushes sort them into rows for stacking and packaging.

The Awesomer

MySQL: Selecting random rows

Given a table named tbl with one million entries, we want to select a random row from this table, fast.
Our table definition looks like this:

create table tbl (
 id INTEGER NOT NULL,
 d VARCHAR(200) NOT NULL,
 INDEX(id)
);


Dense id space

We can generate some test data using a recursive CTE:

mysql> set cte_max_recursion_depth = 100000;
mysql> insert into tbl  -> with recursive c(n, u) as (
 -> select 1, uuid()  -> union all
 -> select n+1, uuid() from c where n < 100000
 -> ) select * from c ;

The Recursive CTE will generate 100k pairs of (number, uuid()).
The initial row is defined in the upper row of the UNION, each subsequent row builds recursively on top of that, by simply counting up.

Since we generate all the values in one transaction, the uuid() is actually static.
That is, because inside a transaction time stops, and the uuid is internally time-based.

Since the id-space is free of gaps, we have rng many numbers between min(id) as min and max(id) as max.
Using the index on id, we can simply generate a random number between these boundaries and select the row.

mysql> select min(id), max(id) into @min, @max from tbl;
mysql> select @max-@min+1 into @rng;

mysql> select * from tbl where id = floor(rand() * @rng) + @min;
+-------+--------------------------------------+
| id | d |
+-------+--------------------------------------+
| 79720 | 13b94bdf-bc1c-11ed-9c65-08606ee5ff82 |
+-------+--------------------------------------+
1 row in set (0.06 sec)

mysql> select * from tbl where id = floor(rand() * @rng) + @min;
+-------+--------------------------------------+
| id | d |
+-------+--------------------------------------+
| 28379 | 13b64d6a-bc1c-11ed-9c65-08606ee5ff82 |
+-------+--------------------------------------+
1 row in set (0.06 sec)


Gaps, and we don’t care

If our table has gaps, and we do not care, we can simply move to an inequality and work with that:

mysql> select floor(rand() * @rng) + @min into @val;

mysql> > select @val, tbl.* from tbl where id >= @val limit 1;
+-------+-------+--------------------------------------+
| @val | id | d |
+-------+-------+--------------------------------------+
| 46346 | 46346 | 13b74a19-bc1c-11ed-9c65-08606ee5ff82 |
+-------+-------+--------------------------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id % 2 = 0;
Query OK, 50000 rows affected (0.71 sec)

mysql> select @val, tbl.* from tbl where id
>= @val limit 1;
+-------+-------+--------------------------------------+
| @val | id | d |
+-------+-------+--------------------------------------+
| 46346 | 46347 | 13b74a1c-bc1c-11ed-9c65-08606ee5ff82 |
+-------+-------+--------------------------------------+
1 row in set (0.00 sec)


Generating truly random rows

Using Python, we can generate truly random rows.

def generate(count = 1000000):
 """ Generate some test data """
 sqlcmd = "insert into tbl (id, d) values ( %(id)s, %(d)s )"

 # ID values with a step of 100, in random order
  # this ues a lot of memory to materialize the list
 id_list = [ i for i in range(0, count * 100, 100 )]
 # but if we want to shuffle, we have hardly any other option 
 random.shuffle(id_list)

 counter = 0
 data = []

 # Write them out, in batches of 1000.
 for i in id_list:
 item = {"id": i, "d": uuid.uuid4()}
 data.append(item)
 counter += 1

 if (counter % 1000) == 0:
 try:
 c = db.cursor()
 c.executemany(sqlcmd, data)
 except MySQLdb.Error as e:
 print(f"MySQL Error: {e}", file=sys.stderr)
 sys.exit()

 data = []
 db.commit()

 db.commit()

and that yields

mysql> select * from tbl limit 10;
+----------+--------------------------------------+
| id | d |
+----------+--------------------------------------+
| 720800 | d6aba075-d30c-4159-a3f9-67e23ac5674e |
| 2548500 | 18fccfa2-4fc6-4642-861b-4c98314cd6f1 |
| 86144900 | e5a58428-c5e1-4a32-a009-88b5877348bf |
| 88949600 | fabbce25-221e-41d3-97e4-8cfa6bdc4816 |
| 18642300 | 6df95b85-0d49-487c-98b0-548980479e16 |
| 59352400 | 4dfa8a3c-95e7-41b6-83f4-1f1c9f647ecd |
| 11149400 | 60d19e1f-1bca-41d2-93a6-1f9af585bbd4 |
| 37822800 | eebeafd8-b08a-483d-88a5-f779de5d6888 |
| 88126400 | 04c4d0ed-ba7c-456f-ac8c-a72448f38621 |
| 65363500 | 876794c9-b3b5-4cda-9acd-dacb4f5a9419 |
+----------+--------------------------------------+
10 rows in set (0.00 sec)

If we had defined the table with a primary key, InnoDB would have kept the data in primary key order – sorted by id.
Since we did not, the output is kept in generative order.


Window functions do not help us here

We can generate row numbers, using window functions:

mysql> select tbl.*, row_number() over () as r from tbl limit 10;
+----------+--------------------------------------+----+
| id | d | r |
+----------+--------------------------------------+----+
| 720800 | d6aba075-d30c-4159-a3f9-67e23ac5674e | 1 |
| 2548500 | 18fccfa2-4fc6-4642-861b-4c98314cd6f1 | 2 |
| 86144900 | e5a58428-c5e1-4a32-a009-88b5877348bf | 3 |
| 88949600 | fabbce25-221e-41d3-97e4-8cfa6bdc4816 | 4 |
| 18642300 | 6df95b85-0d49-487c-98b0-548980479e16 | 5 |
| 59352400 | 4dfa8a3c-95e7-41b6-83f4-1f1c9f647ecd | 6 |
| 11149400 | 60d19e1f-1bca-41d2-93a6-1f9af585bbd4 | 7 |
| 37822800 | eebeafd8-b08a-483d-88a5-f779de5d6888 | 8 |
| 88126400 | 04c4d0ed-ba7c-456f-ac8c-a72448f38621 | 9 |
| 65363500 | 876794c9-b3b5-4cda-9acd-dacb4f5a9419 | 10 |
+----------+--------------------------------------+----+
10 rows in set (0.00 sec)

But since they are generated on the fly, they are not an efficient way to select a random row:
We cannot use Window functions in any interesting context, and using them in a subquery basically forces the database to materialize all the rows before the one we are interested in.
So this is slow:

mysql> select tbl.*, row_number() over () as r from tbl where r = 192383;
ERROR 1054 (42S22): Unknown column 'r' in 'where clause'

mysql> select tbl.*, row_number() over () as r from tbl where row_number() over () = 192383;
ERROR 3593 (HY000): You cannot use the window function 'row_number' in this context.

mysql> select tbl.*, row_number() over () as r from tbl having r = 192383;
ERROR 3594 (HY000): You cannot use the alias 'r' of an expression containing a window function in this context.

mysql> select * from ( select tbl.*, row_number() over () as r from tbl ) as t where r = 192383;
+----------+--------------------------------------+--------+
| id | d | r |
+----------+--------------------------------------+--------+
| 85856500 | 17e04a8a-95e5-4f5f-8aa2-597c2d37dd43 | 192383 |
+----------+--------------------------------------+--------+
1 row in set (4.58 sec)


Selecting randomly from tables with gaps

Without continuous ids, and without a row count we cannot easily select the “n-th record” from a table.
So the best we can do is to select all id-values, and shuffle them, then choose the first row from the shuffle:

mysql> select id from tbl order by rand() limit 1;
+----------+
| id |
+----------+
| 64527400 |
+----------+
1 row in set (0.86 sec)

We can turn this into a full row with a join with almost no cost:

mysql> select * from tbl as t1  -> join (
 -> select id from tbl order by rand() limit 1
 -> ) as t2 on t1.id = t2.id;
+----------+--------------------------------------+----------+
| id | d | id |
+----------+--------------------------------------+----------+
| 24765800 | dcabd753-a357-4f38-a255-e81b0675654f | 24765800 |
+----------+--------------------------------------+----------+
1 row in set (0.82 sec)


Consuming rows

In the previous examples, we have been re-ordering the table randomly for each access (or group of accesses).
The shuffle has not been made persistent.

Often, the problem is not to select a random row, but to consume rows in random order.
We can store a random number with each row, and then use this as an (indexed) ordering key.
Using the knowledge from
the queueing article
,
we can select the item with the highest ordering value, lock it for consumption, retrieve it and delete it.

The idea is to add a column ordering to our table, indexed for fast access.
The ordering value is assigned randomly.
Here, we are creating the values after the fact in batch for one million entries, but in a system you would probably do that for each item as you write the item.

mysql> alter table tbl add column ordering double, add index(ordering);
Query OK, 0 rows affected (20.18 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> update tbl set ordering = rand();
Query OK, 1000000 rows affected (1 min 8.27 sec)
Rows matched: 1000000 Changed: 1000000 Warnings: 0

To consume a random row, we start a transaction, select the row we want, using FOR UPDATE and SKIP LOCKED, and then delete it.

mysql> START TRANSACTION;

-- Two rows with the same ordering value may exist.
-- We can distinguish them by id, and can process one or both of them.
--
-- If another process has a lock on the topmost row, we will get zero results
-- due to the use of SKIP LOCKED.
mysql> select * from tbl where ordering = (select max(ordering) from tbl) for update skip locked;
+----------+--------------------------------------+--------------------+
| id | d | ordering |
+----------+--------------------------------------+--------------------+
| 31106100 | dc12e901-64a0-45a1-8f2e-dee93e3c8ab9 | 0.9999995017424221 |
+----------+--------------------------------------+--------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id = 31106100;
Query OK, 1 row affected (0.00 sec)

mysql> commit;
<actual processing outside of the transaction>

Here, the inner query determines the maximum “ordering” value, which is fast due to the index.
We make use of that value to fetch “a row”.
Nothing prevents multiple rows from matching, so we may get one or more rows.
We take the first (or all values), process it, and delete the processed rows, then commit.

Because we use FOR UPDATE, each row we select will also be exclusively locked, so other consumers cannot touch them.
Because of the SKIP LOCKED, other consumers will not be hanging on locked rows.
Instead, they will simply not see locked rows, so our query may actually even return zero rows in a concurrent context.

Alternatively, you do not strictly process items in order, and want to process them “roughly” in order, but be able to leverage multiple consumers.
A query such as the one below selects one or more items to process (locking them), so that they can be picked up for processing and deleted.

mysql> start transaction read write;

-- This is the first UNLOCKED row available for processing.
--
-- Another process may have a lock on another row with an even larger ordering value,
-- but thanks to SKIP LOCKED, we will not see that. mysql> select * from tbl order by ordering desc limit 1 for update skip locked;
+----------+--------------------------------------+--------------------+
| id | d | ordering |
+----------+--------------------------------------+--------------------+
| 68998800 | bcf7cca2-076d-444b-922b-ae064a1c49a8 | 0.9999983534216865 |
+----------+--------------------------------------+--------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id = 68998800;
Query OK, 1 row affected (0.00 sec)

mysql> commit;

<actual processing outside of the transaction>

For scalability, it is important to keep the interval between START TRANSACTION and COMMIT as short as possible.
Therefore, it is advisable to keep the actual item processing outside the transaction.

Because we do not need to shuffle things each time when we access things, this is actually much faster than “selecting a random row”.

Planet MySQL

Seven Tips to Learn Laravel More Effectively

https://twtv3.ams3.digitaloceanspaces.com/posts/90455478bb71b5642dccd5bbbac98350.jpeg

When it comes to creating online apps, Laravel is a go-to PHP framework. It has many vital features that allow developers to construct websites quickly and easily. It’s also highly fluid, user-friendly, and simple to pick up and grasp and put into practice. 

Many resources are available to assist you in learning Laravel as the community grows. What’s more, how do you decide which is the best? Is there a method of learning that is more suited to your needs?

Here are seven tips to learn Lavarel more efficiently. 

Start with Official Documents

Laravel’s official documentation is a common initial step for novices. No offence to Laravel’s docs, but don’t get me wrong! Documentation writers often assume their audience is familiar with PHP and its associated technologies before they begin writing it.

Installation, for example, does not simply consist of “download and install.” Composer, the terminal, the command line, and setting up a Web server are all necessary skills.

Learn About Different Systems

Secondly, familiarize yourself with the Modal, View, & Controller (MVC) architecture before using Laravel. If you don’t know MVC, you won’t grasp Laravel and its terminology.

Work on Composer

Composer is a PHP dependency management; learn how to utilize it. There is no need to keep track of every one of the libraries and dependencies necessary for the project. To get started with Laravel, you’ll first need to have Composer installed and then install some of its dependencies on your own.

Use Different Sources

One of the most common questions is, “How do I get started?” People’s preferences differ from one another. Reading books or watching instructional videos are two standard learning methods, and each has its pros and cons. Both options are good.

However, it would help if you were on the lookout for anything with good structure and stability. The results you’re looking for won’t come from YouTube or some other random source. Writing consistency is essential. If you don’t, you risk becoming lost and not following through with the rest of the classes.

Also Read: Top 10 reasons to choose Laravel

Try Routing

The core of every Laravel-based online application is routing. When users learn that Laravel does not automate HTTP queries, they panic. Routing in and out of HTTP requests is taken care of by Laravel’s routes file. Laravel’s routing mechanism may be understood if you are acquainted with HTTP techniques.

Focus on Creating

It is crucial to concentrate on creating rather than watching and reading videos if you want to be known in coding. Start coding as soon as possible. After you complete your session, I recommend practising the codes. Moreover, I suggest you take a test at the end of each chapter to improve your morale and help you identify areas of weakness.

Seek a Role Model

When you’re beginning to program, the most challenging part is figuring out how to fix things when they don’t function. Asking for assistance is the best course of action in this situation. Finding a deity who can aid you is essential!

To locate a mentor, where should you look? In both your natural and online social circles. They’ll be more than delighted to assist you if they’re not too busy and your query isn’t ridiculous. See if you can track down the person you’re looking for and then send them a note.

Laravel News Links