Managing Planetscale DB schema with Laravel migrations

https://opengraph.githubassets.com/befba0664babbe9f75ce81cbf06a6d6fa5a0568724da50853489be1ce853f853/x7media/laravel-planetscale

LaravelPlanetScale

Latest Version on Packagist
Total Downloads

This package adds a php artisan pscale:migrate command to your Laravel app which can be used instead of the normal php artisan migrate command when using a PlanetScale database.

Installation

Via Composer

composer require x7media/laravel-planetscale

Configuration & Usage

  1. Login to your PlanetScale account and get your Service Token and Service Token ID from the organaization settings. Also take a note of your organization name and production branch name as well for the next steps.

  2. Add the following database level permissions to your Service Token for your app’s database:

    • create_branch – Create a database branch
    • delete_branch – Delete a database branch
    • connect_branch – Connect to, or create passwords and certificates for a database branch
    • create_deploy_request – Create a database deploy request
    • read_deploy_request – Read database deploy requests
  3. From the database settings screen on PlanetScale, click the checkmark to enable the “Automatically copy migration data” settings. Select “Laravel” from the migration framework dropdown and it should fill it “migrations” for the migration table name. Then save the database settings. This will allow migration status to be synced across PlanetScale database branches.

  4. Setup the following enviroment variables in your app with the appropriate values:

PLANETSCALE_ORGANIZATION=

PLANETSCALE_PRODUCTION_BRANCH=

PLANETSCALE_SERVICE_TOKEN_ID=

PLANETSCALE_SERVICE_TOKEN=

Additonally yuou’ll need to make sure your database name is set under:

DB_DATABASE=

OR

Optionally you can publish the config:

php artisan vendor:publish --tag=laravel-planetscale-config

Then customize the values in the config. NOTE: If you take this approach we STRONGLY RECOMMEND that you still use enviroment varibles or some other secrets storage at least for your service token and service token ID for security.

  1. Replase the php artisan migrate command in your deployment script or process with this:
php artisan pscale:migrate

NOTE: The pscale:migrate command supports the same options are Laravel’s built in migration command, and will pass those options along to it when it gets to that step in the process.

FAQ’s

Why is this necessary?

PlanetScale has alot of advantages when using it as your application’s production database. However it handles your database and schema migrations in a somewhat unusual way.

It uses branches for your database. A branch can be production or development. You’ll want to use a production branch for your app in production because that afford you extra features like automatic backups, however you cannot perform schema changes directly against a production branch. Instead you should create a new development branch based on your production branch and perform your schema changes on that than merge that back into your production branch just like you would do with your code in Git.

This package uses PlanetScale’s Public API to automate the process of creating a new development branch, connecting your app to the development branch, running your Laravel migrations on the development branch, merging that back into your production branch, and deleting the development branch.

Are there any notable limitations to PlanetScale’s branching?

Yes, there is one BIG caveat. That is branching and merging is for schema only. So you will need to seperate your schema migrations from your data migrations. Use this to run your schema migrations and run your data migrations seperatly against your production branch.

An alternative method is to demote your production branch back to a development branch, then you can mix schema and data migrations. Then when that is finished promote the branch back to a production branch. But that is currently a manaual process. I have however made a request with the PlanetScale team to make a slight change to their API that would allow this demote-promote process to be automated, and if that change is made I will update this package. However I ultimately have no control over if or when that will become possible.

Change log

Please see the changelog for more information on what has changed recently.

Testing

Contributing

Please see the contributing guidelines.

Security

If you discover any security related issues, please email info@x7media.com instead of using the issue tracker.

Credits

License

MIT. Please see the license file for more information.

Laravel News Links

That Senate bill to “ban” TikTok? Read the terrifying fine print and kiss your civil liberties goodbye

https://www.louderwithcrowder.com/media-library/image.png?id=33370344&width=980

I am feeling quite bamboozled by this whole "ban TikTok" thing. I was fully on board, but I actually hadn’t read the proposed bill. Silly little me thought that when Congress said they wanted to ban TikTok, they just meant they wanted to ban TikTok. But of course, this is another onion of a bill with little Easter eggs hidden throughout. And these are some pretty scary Easter eggs.

There are actually two proposed bills, but the one we’re talking about is called the "RESTRICT Act." It has support from both parties as well as the White House. And it’s basically a Patriot Act for the internet, as Greg Price on Twitter put it. It gives the government the authority to go after anyone they deem a national security threat. Which could mean actual terrorists, sure. Or it could mean the sad white kid in the basement who excels in the art of meme-making. Either way, the government would have access to basically anything they own that connects to the internet.

The penalties for a violation range from 20 years in jail, $1M in fines, and/or seizing your property. All just because we want the Chinese Communists to stop subverting our youth with half-naked dancing girls. I guess that’s too much to ask.

The bill also allows the White House, through the Commerce Department, to ban social media, gaming, and payment apps. Meaning they can ban video games, video game companies, and might even have the power to go after crypto.

The bill also refers to the ability to ban transactions. The term "transaction" is defined as a "current, past, or potential future transaction." Basically, anything Uncle Sam wants it to be.

But wait, there’s more! All the hullabaloo around TikTok is because it poses an imminent threat from China, a foreign adversary. But in this bill, a "foreign individual" can also be an American citizen! Yaaaay!

And for the cherry on top, any details about each usage of the act is exempt from FOIA. Just cuz. So as much as I hate to agree with the Libertarian Party on anything, it seems they got this one right. You can check out their whole Twitter thread for yourself. And let’s hope this bill doesn’t pass.

><><><><><><

Lily is a Zoomer college dropout who somehow landed a writing gig here at LwC.com. In her spare time, she enjoys going for runs, touching grass, and occasionally tweeting tweets for fellow tweeters.

Facebook doesn’t want you reading this post or any others lately. Their algorithm hides our stories and shenanigans as best it can. The best way to stick it to Zuckerface? Bookmark LouderWithCrowder.com and check us out throughout the day! Also, follow us on Instagram and Twitter.

Louder With Crowder

How I Built a Weather App Using Three Python Frameworks

https://blog.finxter.com/wp-content/uploads/2023/03/image-399.png

5/5 – (1 vote)

Python has several web frameworks for creating web applications.

are some of them.

If you want to become a Python web developer, the importance of learning Django and Flask plus other frameworks can never be overemphasized. There is no better way to learn than working on projects using web frameworks.

???? Recommended: Flask vs Django: Comparing the Two Most Popular Python Web Frameworks

In this three-part tutorial series, I will walk you through the process of building a weather app using three Python frameworks: Django, Flask, and Streamlit. We will start with Django, and if you have been following my project tutorials on Django, this will be an easy ride for you.

Then, for the very first time, I will be creating Python projects using Flask. We will learn this in part two. In the final part of this series, we will see how to create this same application using Streamlit, and have it hosted on Streamlit Cloud for others to use.

A Weather Application

A weather application enables users to get real-time weather information on cities they select. Using powerful web frameworks like Django makes building such an app a fairly easy job for Django developers. All we need is a public API to get real-time information.

We will use the OpenWeatherMap API. So, if you have not already done so, head over to the website and register to get an API key. The API key enables us to benefit from the services rendered by OpenWeatherMap. Make sure you keep your API key safe. We are going to follow best practices for using the API key.

Getting Started

Follow these five steps to set up Django on your system.

  1. Create a folder for this project using any name of your choice and cd into it.
mkdir django-project && cd django-project
  1. Create and activate a virtual environment.
python3 -m venv .venv
. .venv/bin/activate
  1. Install the necessary modules and dependencies.
pip install django requests tzdata
  1. Create a requirements.txt file to store the module versions
pip freeze  > requirements.txt
  1. Then, fire up the local server using the command python3 manage.py runserver to check if everything was installed successfully.

Creating Django project and app

Run this command in your terminal to create a Django project:

django-admin startproject weather .

Don’t forget the dot to create the project in the current directory. The mange.py file is used the execute some Django commands. So, let’s use it to create Django app.

python3 manage.py startapp app

Feel free to use any name of your choice. I briefly explained the function of those files inside the project and app folders. Check it or the documentation if you want to learn more:

???? Recommended: How I Created a URL Shortener App with Django

We have to let Django know that a new app is created. We will do this in settings.py file. Open it and scroll down to INSTALLED_APPS, and add the name of the app.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # custom app
    'app',
]

We are not working with models in this project. So, everything is going to be simple. Let’s now implement the search functionality using the API key.

Using the OpenWeatherMap API

In your app_level folder, create a file called secret_key.py. Then, add your API key there like this:

KEY = 'YOUR API KEY' 

Create another file inside the folder and call it weather.py. You will import the API key there.

import requests
from datetime import datetime
from .secret_key import KEY

def getWeather(city):
    url = f'https://api.openweathermap.org/data/2.5/weather?q={city}&appid={KEY}&units=metric'
    response = requests.get(url).json()
    current_time = datetime.now()
    formatted_time = current_time.strftime('%A, %B %d %Y, %H:%M:%S %p')
    context = {
        'city': city,
        'description': response['weather'][0]['description'],
        'icon': response['weather'][0]['icon'],
        'temperature': 'Temperature: ' +  str(response['main']['temp']),
        'country_code': response['sys']['country'],
        'wind': 'Wind: ' + str(response['wind']['speed']) + 'km/h',
        'humidity': 'Humidity: ' + str(response['main']['humidity']) + '%',
        'time': formatted_time
    }
    return context

We import the modules we will use, including the API key.

Then we create a function with a city parameter. This function uses the requests module to get weather information of a given city using the API key. We select only the items we need; and wrap them in a dictionary. We are going to import this function to the views.py file.

Can you see how we use the API key without exposing it?

Creating Views

Open the views.py and let us add in some code.

from django.shortcuts import render
from .weather import getWeather

# Create your views here.

def index(request):
     try:
         if request.method == 'POST':
             city = request.POST['city']
             context = getWeather(city)
             return render(request, 'home.html', context)
         else:
             city_weather = {}
             context = {'city_weather': city_weather}
             return render(request, 'home.html', context)
     except:
        return render(request, 'error.html')

It’s a good practice to create a separate file for the weather information and have it imported into views.py file.

This makes your code neat and readable.

The index() function uses the try statement to make sure the code runs without errors. It checks if the request method was POST, if so, it retrieves the city name and passes it to the getWeather() function.

Finally, it renders the result on the home.html web page. But if there was an error. The error.html web page is displayed.

Registering URLs

Let’s create and register the urls.py file. This file registers all URLs created in the app folder.

from django.urls import path
from .views import index, error

urlpatterns = [
    path('', index, name='home'),

]

We also have to register the application URLs. Go to your project-level folder and open the urls.py file.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

Creating Templates

Last but not least is templates. Create a templates folder, then go to the settings.py file under the TEMPLATES section.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # add these
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Next, create three files inside the folder with the names, base.html, home.html, and errors.html.

base.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Weather App</title>
    <!-- getting bootstrap5 from CDN -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    {% block content %}

    {% endblock %}
</body>
</html>

All other HTML files will inherit from this base.html file. We are using Bootstrap to style the web pages. Now the home.html.

<!-- extends is for inheriting from the base.html -->
{% extends "base.html" %}
{% block content %}
<div class="row justify-content-center my-5">
    <div class="col-md-5">
        <div class="mt-4 p-5 bg-success text-white rounded mb-3">
            <h1>Django Weather App</h1>
        </div>
        <form action="." method="POST">
          {% csrf_token %}
          <div class="input-group">
            <input type="text" required class="form-control" name="city" placeholder="Search City...">
            <div class="input-group-append">
              <button class="btn btn-success" type="submit">
                Search
              </button>
            </div>
          </div>
        </form>
        <hr>
        <div class="card">
           <div class="card-body">
                <img src="http://openweathermap.org/img/w/.png" alt="">
            
                <div class="card-text float-end"></div>
                <div class="card-text"><h5>, </h5></div>
                <div class="card-text"><h6></h6></div>
                <div class="card-text"><h6></h6></div>
                <div class="card-text"><h6></h6></div>
                <div class="card-text"><h6></h6></div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

Django syntax makes it easy to dynamically write to web pages. If you check back on weather.py, you will notice the return results wrapped in a dictionary were dynamically written to the web page using the form.

The form with the action=dot signifies the current URL. The csrf_token protects against malicious attacks.

Finally, the error.html file.

<!-- extends is for inheriting from the base.html -->
{% extends "base.html" %}
{% block content %}
<div class="row justify-content-center my-5">
    <div class="col-md-5">
        <h1>Page Not Found</h1>
        <p>Make sure you are connected to the internet or you are entering a valid city name</p>
        <a href="{% url 'home' %}" class="btn btn-secondary">Home</a>
    </div>
</div>
{% endblock %}

The {% url ‘home’ %} is another way to refer to the home.html web page. Remember the ‘home’ in the urls.py file? Let’s now test the project on the local server. Run python3 manage.py runserver to open the local server.

Conclusion

We have successfully come to the end of this tutorial. We have learned how to create a weather app using Django. The full code is available on my GitHub page.

You have undoubtedly learned many things that can help you while working on projects. Watch out for the second part of this series, where I created the same app using the Flask framework.

Be on the Right Side of Change

You Can Download the Out-of-Print ‘Zelda: Breath of the Wild’ Explorer’s Guide for Free

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/be5dd0207d3870474a99f79ad89bbd6e.jpg

Photo: Red Herring (Shutterstock)

In anticipation of the new The Legend of Zelda: Tears of the Kingdom set to release on May 12, which you can pre-order for $20 less than the regular price, Nintendo has released The Legend of Zelda: Breath of the Wild – Explorer’s Guide free for you to download. Here’s what you need to know.

What is The Legend of Zelda: Breath of the Wild – Explorer’s Guide?

The Legend of Zelda: Breath of the Wild Explorer’s Guide originally came within a bundle package in 2017.  The Legend of Zelda: Breath of the Wild Explorer’s Edition bundle included the game, an explorer’s map, and the guide. The e-guide is a 96-page PDF walkthrough with information on gameplay mechanics and the world of Hyrule that beginners will find helpful and veterans might find interesting.

What is interesting about this free PDF version is that it is missing pages 73-84, which included sections about “Horsing Around,” “Hyrule’s Wild Side,” “Fiercer Foes,” “The Many Faces of Hyrule,” “The Four Tribes,” and “Great Fairy Fountains.” The reason for the omissions are not known, but Polygon has ruled out that it is for spoiler reasons. Perhaps it’s just an error from Nintendo that might be fixed later.

If you did not get the physical guide back when it was basically free with the game, the price has been inflated quite a bit from its $60 bundle cost, if you could still manage to find it new from reputable stores. The physical version sold out some time ago, although you could still find it for reasonable prices at some second-hand markets.

The timing of the release seems to be clear: At this point, most people will probably not be looking to buy the guide to play a six-year-old game. More than likely, the strategy seems to be to get people hyped about the upcoming Zelda game and get people to finish The Legend of Zelda: Breath of the Wild.

Lifehacker

Watch 10 minutes of ‘Legend of Zelda: Tears of the Kingdom’ gameplay

https://s.yimg.com/os/creatr-uploaded-images/2023-03/1c0fa3b0-cd78-11ed-bfff-507b777f076f

As promised, Nintendo has showcased 10 minutes of The Legend of Zelda: Tears of Kingdom gameplay — and it’s a useful preview if you’re wondering just how the developers will improve on Breath of the Wild‘s formula. Most notably, producer Eiji Aonuma notes that fusing objects plays an important role in the game. You can build stronger weapons, and even craft vehicles like powered boats and hovercraft. Enemies can use fused weapons too, though, so you can’t assume that a favorite combat strategy will work.

The demo video also shows a way to reach the floating islands above Hyrule (by using a recall ability on an elevator stone), and what happens if you fall or jump off. You have full control all the way down, so you can glide to distant areas or plunge quickly toward the ground. Many mechanics appear familiar, so you won’t have to relearn the fundamentals.

And yes, Nintendo plans to cater to Legend of Zelda devotees with special edition hardware. The company is releasing a Tears of the KingdomOLED Switch (shown below) for $360 on April 28th, weeks ahead of the game’s May 12th launch. You won’t get a copy of Tears, unfortunately, but you will get lavish artwork on the Switch itself, the Joy-Con controllers and the dock. If you already have a Switch, you can also buy Tears-edition Pro Controller ($75) or carrying case ($25).

Nintendo Switch OLED 'Tears of the Kingdom' model
Nintendo

This article originally appeared on Engadget at https://www.engadget.com/watch-10-minutes-of-legend-of-zelda-tears-of-the-kingdom-gameplay-145613610.html?src=rssEngadget

Langdon Tactical Offers Completely Free Training Video Series

https://cdn.athlonoutdoors.com/wp-content/uploads/sites/6/2023/03/langdon-tactical-03.jpg

The importance of quality education and training when it comes to firearms ownership and operation is absolutely paramount. Many who are new to firearms feel it can be daunting and have a lot of questions. Particularly those who consider making everyday carry a part of their lifestyle. For this reason, we introduce Langdon Tactical and its video training series and comprehensive resource.

Langdon Tactical Change the Game

Quality, thorough, thoughtful, and well-designed training content to serve firearms owners across the full spectrum of experience is important. However, no single platform has truly hit the mark.

This is where Ernest and Aimee Langdon enter the scene with designs to change the game. They are the president and vice president of the renowned firearms customization outfit Langdon Tactical Technology (LTT).

The Backstory

Ernest’s background includes 12 years of active-duty service in the United States Marine Corps. Additionally, he has more than 30 years of competitive shooting experience. His competitive accolades include a Grand Master rating in USPSA (United States Practical Shooting Association). Likewise, he has accreditation as a Distinguished Master in IDPA (International Defensive Pistol Association). Finally, he has ten National Championships and two World Speed Shooting titles.

Aimee is a global business professional with more than 16 years of accomplished professional business development, sales, and marketing experience. She has podiumed three times at The Tactical Games—twice in first and once in second place at the 2021 Nationals. While leading Business Development and Operations for LTT, she trains at a grueling pace and is an energetic and dedicated mom.

Ernest and Aimee Langdon of Langdon Tactical.

This couple not only helms the day-to-day business at LTT but are also the masterminds and producers behind LTT Discover. LTT is renowned for customizing and converting exceptional stock firearms platforms into extraordinary competition-quality enhanced guns. LTT Discover is a groundbreaking firearms education and empowerment platform.

Free Video Series and Comprehensive Training Resource

As noted in the mission statement of the LTT Discover website, the completely free video series and comprehensive training resource is “…aimed at bringing forth great information and resources to better guide and educate those looking to own a firearm without intimidation or demanding perfection.”

The curriculum is guided, based on experience level and keynotes distilled from the unique backgrounds and perspectives of both Aimee and Ernest. Likewise, it draws insight and contributions from influential pillars and experts in the 2A community. As a result, the series serves as a very inclusive, welcoming, well-rounded resource.

I recently navigated the series and website myself. Having experience with what else is (and isn’t) out there, I feel LTT Discover is genuinely a refreshing new approach. Even the most well-trained and experienced in the firearms community should find great value throughout.

Screenshot of Ernest Langdon providing firearm instruction in LTT Discover video.

I recently had a chance to chat with the founders about their journey together. We discussed the inception of the LTT Discover platform and learned what is in store for the community. Specifically as it applies to the future of firearms education and training.

QUESTIONS & ANSWERS

How did you two meet each other?

AIMEE: We worked together at a robotics company for six years. We both started new chapters personally and professionally and found each other romantically.

What’s life like between the business, family, and training? How do you juggle it all?

ERNEST: Balance. We are constantly balancing family time, work time, and personal time and sometimes we fail all the way around. But fitness and nutrition are pivotal components of our family unit. We are active together and love to cook.

AIMEE: Outside of our personal shooting training, we attend other classes and courses with other instructors to continue to learn from other people.

I understand the Discover platform was partially developed because of your experiences training together. What’s that dynamic like at the range?

AIMEE: Have you ever tried to teach your spouse something? HA! We shoot together all the time and as a couple, manage it better than most.

ERNEST: In all the years we have been going to the range, we can count on one hand the number of times we silently packed up and left the range. Learning when and how to instruct as well as how to be a student while separating the relationship is something we have figured out.

AIMEE: It’s tough to teach and be corrected all the time. However, separating the emotion from the task often helps. And sometimes, he just needs to be reminded, “positive reinforcement helps too,” or “hey, can we just shoot today?”

ERNEST (laughing): Sometimes, I just need to keep my mouth shut.

What were some of the main motivations or “aha! moments” that led to you beginning to consider developing LTT Discover?

ERNEST: We began to develop Discover as we found a missing gap in education and information available for people who are not tactical, LE or related to the LE/MIL community. Being business owners, we are often asked for direction, information and/or training. As we started to get bigger, more people were asking for assistance. We were looking for places to send them.

AIMEE: Guilty by association, the assumption was that early on, I was just as proficient and experienced as Ernest was, and the reality is, at that time, I hadn’t even touched a handgun before we got together. The “Carry Journey” component of Discover was created based on many gun owners’ first-time experiences around firearms or in making the decision to own a firearm while also incorporating health and fitness as a more complete mindset.

Being in the tactical industry, it’s often assumed or impressed upon others that if you are going to own a firearm, you have to do things a certain way and if you don’t, then you shouldn’t even own a firearm. It’s very intimidating for millions of people and many of the gun owners today.

Who is LTT Discover for?

ERNEST: LTT Discover is for everyone—those thinking about firearms ownership to those who own firearms and who carry every day.

LTT Discover screeshot.

When it comes to the 2A space and industry, how important is community and community building to you, and why?

Aimee: Community and Community building is huge, it’s very important to us. We believe a community provides real and raw emotion, tied to being caring and helpful to individuals in a positive way.

A strong community provides a safe place where people can seek information and ask questions without the fear of being belittled or made fun of because they don’t understand and/or are new and don’t know things that some people consider common knowledge.

Ernest: Being a part of a community makes people feel comfortable to ask a question, agree OR disagree, and be guided by trusted and real individuals from a real raw perspective, position or experience background.

What has the initial response to LTT Discover been since its launch?

AIMEE: We are blown away by the positive response from Discover. We have received so many thanks and “ah-ha’s” from men and women alike who feel like the information is proficient, straightforward, and not intimidating. Many enthusiasts who are gun owners have been able to use it as a tool for friends and loved ones to share information and thoughts from real individuals.

As a closing question, what are your personal hopes and dreams for the impact that LTT will have on the industry and the public at large?

AIMEE: As a brand, we hope Langdon Tactical will be a resource not only for products and training (as it is today) but also as an educational resource that provides a welcoming community guiding people to be more confident, self-reliant, and empowered as individuals.

Thank you, Aimee and Ernest, for sitting down to share this exciting new resource. I expect it will help grow the community in a much-needed way. And I’ll definitely be watching to see what comes next.  

Ernest and Aimee Langdon of Langdon Tactical.

To learn more about Langdon Tactical Technology and to explore the LTT Discover platform, visit LangdonTactical.com and LTTDiscover.com.

LTT Discover screeshot.

This article was originally published in the Personal Defense World April/May 2022 issue. Subscription is available in print and digital editions at OutdoorGroupStore.com. Or call 1-800-284-5668, or email subscriptions@athlonmediagroup.com.

Didn’t find what you were looking for?

The post Langdon Tactical Offers Completely Free Training Video Series appeared first on Personal Defense World.

Personal Defense World

Go inside Sigma’s factory to see how lenses are made

https://2.img-dpreview.com/files/p/E~C213x0S3413x2560T1200x900~articles/5410838737/20230228-DSC01945_-_shipping_and_receiving.jpeg

Introduction

If you’ve ever bought a new lens, you know the joy of removing a beautiful, pristine optic from its box and attaching it to your camera for the first time. But have you ever wondered what it takes to design and build that lens? During a recent trip to Japan, we had the opportunity to go behind the scenes at Sigma’s lens factory in the city of Aizu to answer that question, and we’re going to walk you through how it’s done, step by step.

Most photographers are familiar with Sigma, but maybe not with its unique history. Sigma is a family-owned business founded in 1961 by Michihiro Yamaki. Mr. Yamaki was an engineer at a small optical company that made binoculars, cameras and video lenses. When the company went bankrupt, some of its suppliers, needing new clients, approached Mr. Yamaki about starting a new business, and Sigma was born.

Today, Sigma has over 1,700 employees, nine subsidiaries in eight countries, and annual sales of 42 billion yen (about $322 million).

Sigma’s business today

As Sigma’s current CEO, Kazuto Yamaki, explained in our recent interview, Sigma has a business philosophy of ‘small office, big factory.’ It has a minimal administrative, sales and marketing staff and prioritizes investment in engineering and manufacturing. This explains why about 75% of the employees at the company’s headquarters in Kawasaki, Japan, are engineers.

Sigma opened its current factory in Aizu, about 300km north of Tokyo in Fukushima Prefecture, in 1974 and it’s home to about 1,500 of Sigma’s employees – the majority of its workforce. The proximity means that Sigma teams can quickly meet in person to resolve problems when needed to solve engineering and manufacturing challenges. This is Sigma’s only factory, and all of its products are made here.

Above: Sigma’s factory in Aizu, Japan.

Sigma’s Aizu factory

Sigma’s factory covers almost 72,000 square meters of floor space (approximately 775,000 square feet) and produces 80,000 lenses and 2,000 cameras annually. It’s a vertically integrated factory, meaning that almost every aspect of manufacturing, including the individual parts that make up each lens – right down to the screws – are produced here.

From the company’s early days, Michihiro Yamaki believed that to make a good product, working with local people and businesses was essential. That approach continues to this day; all of Sigma’s suppliers are located in the northern part of Japan. Essentially, Sigma aims to do everything by itself and with local partners, an approach that paid off during the global pandemic. Unlike companies with complex global supply chains, Sigma was able to keep its factory in operation during that time.

With that background, let’s dive into how lenses are made.

Above: The Sigma’s Aizu factory in 1974 and today, with Mt. Bandai behind. (Image courtesy of Sigma)

Lens testing room

Since optics are the core of any lens, we’ll start with glass. Before diving into the manufacturing process, let’s talk about how Sigma establishes performance metrics for every lens it manufactures.

Each time a new lens is designed, a high-quality master copy is created which is used for benchmark testing; it establishes a baseline performance spec for each new interaction constructed. This baseline becomes the reference point for all Modulation Transfer Function (MTF) machines used throughout the lens manufacturing process, ensuring that each lens meets the design specification for resolution. Sigma designs and builds its own MTF machines in-house.

Testing of the master lens takes place on a Trioptic measurement machine, one of only a few of its type in Japan. It can measure the range between the minimum focusing distance and infinity for all of Sigma’s lenses and uses collimators up to 1000mm.

Glass: lens blanks

Most lens elements start as lens blanks, glass disks with a slight curve. Before any grinding occurs, lens blanks have an opaque, white appearance. Sigma uses lens blanks from Hoya to manufacture its lenses.

Glass grinding

The first step in the lens manufacturing process is to roughly grind out the curve of the lens. Each lens blank is attached to a plunger that guides it into a machine where the glass is ground to the correct curve for the lens. Since this part of the process is intended only to create the right shape for the lens, it still appears somewhat opaque when finished.

A second, more refined precision grinding step is then performed, which gives the lens its clear, smooth finish.

There are about 330 machines used in the glass manufacturing process at Sigma’s Aizu factory, and every few minutes a technician is checking one with a gauge to ensure that its curve is correct.

Lens polishing

After the lenses are ground, the third and final step is polishing. Lenses are set into a machine on polyurethane pads mounted in a mold that matches the final shape or curve of the lens. These grind the lens using a special polishing paste, typically cerium or zirconium oxide. The process usually takes two to ten minutes, depending on the size and type of the lens.

Glass molding

Not all glass elements are ground. Aspherical optics are manufactured through glass molding using one of two processes, depending on their size. Smaller elements begin life as what looks like a bulbous glob of clear optical glass, while larger elements begin as pre-formed glass units.

In both cases, these pieces of glass are put into molds and pushed through a machine that presses them into their final shape using high pressure and heat. Sigma currently manufactures aspherical elements up to 84mm in diameter. Sigma also makes its own molds for manufacturing aspherical lenses, part of its philosophy of building its own tools in-house to maintain quality control.

Aspherical lens manufacturing is one of the better-guarded parts of the lens manufacturing process and something that makes lenses unique, so we were asked to refrain from taking photos in this area. Instead, I’ve included a picture above of one of my favorite Sigma lenses, the 14mm F1.8 Art, which features a front aspherical element that’s 80mm in diameter.

Lens centering

After glass elements are formed and coated, they receive a final grinding around the edges to make sure the diameter and thickness of the edges of the elements are within specifications and will mount correctly inside the lens. This also ensures that the glass elements will be optically centered inside the lens housing.

Lens coatings

Once lenses are polished or molded, it’s time to apply Sigma’s Super Multi-Layer coatings, which suppress flare and ghosting. Before applying coatings, each lens is visually inspected for dust. The lens is then loaded onto a ‘planet,’ a dome-shaped device with inserts for specific lens elements.

The planets are then loaded into machines in which special chemicals have been evaporated into a chamber. The planet rotates inside the device, evenly spreading the vaporized chemicals onto the lens elements, before holding them to be cured by UV light.

Lens caulking, joining and bonding

Once the individual optical elements are manufactured, those that get grouped in a lens go through a process called caulking and joining. Each element is placed into a plastic frame, and high heat and pressure are used to fix them into place, creating a single unit made of multiple lens elements.

A separate process called lens bonding (photo above) is used when two to three elements must be bonded directly with no space in between. The two lenses are joined with a special adhesive, and a machine ensures that both lenses are optically centered. The bonded lenses are then exposed to UV light to cure the adhesive.

Metal processing

Now that we’ve covered glass, let’s move on to the rest of the manufacturing process, starting with metals. A lens has many metal parts, so metal processing covers a large part of the factory floor, producing components out of materials like steel, aluminum and brass.

The automated blue machines visible in the photo above carry out the process of cutting out, shaping and drilling holes in metal for a perfect fit. The process is quick, often taking only a few minutes per part. The factory runs about 160 of the machines you see in the photo.

Metal processing

Although numerous parts are produced in this factory area, lens barrels and bayonet mounts are the most recognizable. This photo shows freshly milled inner rotation barrels for lenses before any surface treatment has been applied.

Recycling

The machining process that turns metal blocks into lens components produces metal waste, like the shavings in this photo. Sigma captures this material and works with a local recycling facility to ensure the materials are repurposed rather than landing in a landfill.

Metal pressing

Some metal parts are stamped out by machines rather than being machined individually. In this case, a strip of metal is fed through a pressing machine by what looks like a giant roll of metal tape.

Metal pressing

And here’s the final product you saw being stamped out on the previous page: metal plates that help control the movement of the aperture blades on a lens.

Magnesium processing

For safety reasons, magnesium parts are machined in a separate building that isn’t connected to the main factory. Magnesium can be flammable, mainly when it’s in a fine shaving or powder form – precisely the forms you tend to produce when milling parts out of metal. As a result, this facility has extra thick concrete walls that offer protection in the event of an accident.

Magnesium is used for many components because it’s strong and durable yet lighter than aluminum. This allows parts to be smaller and lighter than if they were made from aluminum, but there’s a tradeoff: magnesium is more costly. As a result, it’s not used for everything, but only for parts where durability and light weight matter.

Magnesium components start as die-cast parts, one of the few items Sigma doesn’t produce in its factory. There are only a small number of suppliers for die-cast parts worldwide, and Sigma only sources die-cast from a limited number of suppliers in Japan. This photo shows a die-cast lens collar on the left and a fully machined version on the right.

Magnesium machining

These automated machines cut out, shape and drill holes in the die-cast part with high precision. After milling, each piece goes through a cleaning process to remove oils left over from production, then receives a corrosion-resistant coating to protect the metal. Once milling is complete, each part is measured by a machine to make sure it’s within the specified tolerances for the part. In this photo, you can see a tripod collar mounted to a machine.

At any given time, there are about 20 machines milling parts from die-cast magnesium. For safety, each machine is equipped with specialized fire extinguishing equipment explicitly designed for magnesium fires.

New tool and mold creation

Sigma’s philosophy is to control as much of the manufacturing process as possible in its factory, as that allows them to better control the quality of everything it produces. This extends to the molds and tools used to manufacture its products.

This area isn’t automated. Prototypes and parts are handmade, as seen in the photo above. Hand-made parts become blanks and are used to create the injection molds used to manufacture many components. This is also where Sigma builds the specialized tools required to build a new product, typically with a focus on making the assembly process more efficient.

Injection molding

Molds for plastic or pressed parts are made using a process called electronic discharge machining (EDM). This thermal process removes material by applying discharging sparks in the gap between an electrode and the part being manufactured.

Once on the assembly line, viscous plastic is fed into the mold through the center of the mold. A separate series of tubes delivers coolant to the mold, causing the plastic parts to harden. Around 40 injection molding machines are making parts on the assembly line at any given time, and molds will be rotated in and out of production depending on what products are being produced.

Surface mounting

Surface mounting refers to mounting electronics onto circuit boards for lenses. As with many things, Sigma manufactures circuit boards in-house. Baseboards are fed into one end of a machine where soldering paste is applied and heated to spread out the paste evenly. Components are then fed into the machine from rolls that look like tape and stamped onto the board.

Surface mounting

A 3D photo test of each board confirms that all the parts are in the correct positions, followed by an X-ray check. There are about 20 machines in the factory building circuit boards.

The board in this photo is a two-sided circuit board. One side has been printed and is now ready to feed back through the machine for surface mounting on the opposite side.

Painting, printing and surface treatment

Once metal parts like lens barrels have been milled, and any necessary surface coatings applied, it’s time for a paint job. Each part is mounted on a metal jig which spins in circles as the paint is sprayed on, ensuring an even coat of paint. These painted parts are then dried in ovens.

Some materials, like those made of aluminum, may receive a black anodized coating instead.

Printing

Most of the reference markings on a lens, like scale windows and apertures, as well as labels on accessories like lens hoods, are printed or painted on. A technician applies the ‘Sigma’ logo to part of a lens barrel in this photo.

Electroplating

Electroplating is used to apply a chrome surface to metal parts, which makes them more durable. The most recognizable parts to go through the electroplating process are the brass lens mounts for each lens, which are chrome-plated here. Some smaller metal parts are plated here as well.

Final assembly and quality assurance

Once all lens elements are made and all parts have been manufactured, surface treated and painted, they meet at the final assembly line. In this clean room environment, each line is set up based on what models are in production on a given day. A single assembly line extends from the first set of parts to the final build.

Each lens’ alignment is performed using Sigma’s in-house designed and built MTF machines to adjust and confirm that they meet MTF specs. Although total assembly time varies by product, it can take as little as 30 minutes to assemble one lens, but it can certainly extend to longer periods for complex products.

After assembly, lenses are sent to the quality assurance division, which checks them using an MTF measuring machine. Additionally, they are inspected for dirt, surface scratches and other anomalies, and to confirm that zoom mechanisms, apertures and electronic contacts all work correctly. Some products may go through a resolution test at this stage as well.

Packing and shipping

Products arrive in the packing and shipping area without serial numbers. Until a product receives a serial number, it’s like a person without an identity. Once a serial number is assigned, the lens learns where it will be shipped.

Finished products and accessories are matched together and boxed in retail packaging, then loaded into large cardboard shipping boxes based on their final destination.

Finished product storage

The final step before a product leaves the factory is to be placed into the finished product storage area. With over 60 lens models in production across multiple lens mounts, there are a lot of lenses in this room. Products don’t sit here long – Sigma’s factory is producing at capacity, and there’s a constant need to clear this space to make room for new products coming off the assembly line.

Trucks arrive in the evening to ship boxes off to Narita airport in Tokyo, where they will be sent to distributors or subsidiaries worldwide.

I’m pretty sure the Ark of the Covenant is hiding in here somewhere.

Customer support and service

In addition to manufacturing, the Aizu factory serves as a center for Sigma’s customer support services. Most items received for repair here are from Japan (most countries will have their own service centers). However, products from other regions may be sent here if they require specialized repair.

Once a product is checked in, it’s handed over to one of Sigma’s ace repair technicians, who will repair it to Sigma’s original specifications, ensuring that it does so using the projection room shown on the next slide.

Projection room

The projection room, located next to the customer support and service area, is used to test products before and after repair. On the opposite side of the room, there’s a reverse projector for testing Sigma’s cinema lenses.

Sigma’s standard practice is to test lenses on both the resolution chart and MTF machine to ensure that they meet Sigma’s product specs before returning them to customers.

Additionally, technicians will even go outside to take real-world before and after photos to check a lens depending on the nature of the repair, for example to check for flare.

Sigma museum

Of course, no visit to Sigma would be complete without a trip to the Sigma museum, where it’s possible to see cameras and lenses past and present. There’s a lot to see, including modern lenses, classic lenses, SA-mount lenses and even cameras, like Sigma’s SD10 DSLR or compact Merrill models.

Finding some of the lenses you used early in your photography career is a fun, nostalgic trip down memory lane.

Articles: Digital Photography Review (dpreview.com)

Modelling Busines Processes in Laravel

https://laravelnews.s3.amazonaws.com/images/modelling-business-processes-in-laravel.png

As developers, we often map business processes to digital processes, from sending an email to something quite complex. Let’s look at how to take a more complicated process and write clean and elegant code.

It all starts with a workflow. I tweeted about writing this tutorial to see if there would be any feedback on business processes people would find helpful – I only really got one response, though.

So with that in mind, let’s look at the Order/Shipping process, something with enough moving parts to get the idea across – but I won’t go into too much detail from a domain logic perspective.

Imagine you run an online merch store, have an online shop, and use a dropshipping service to send merch out on demand when an order is placed. We need to think about what the business process might look like without any digital help – this allows us to understand the business and its needs.

An item is requested (we are using a print-on-demand service, so stock isn’t an issue).
We take the customers’ details.
We create an order for this new customer.
We accept payment for this order.
We confirm the order and payment to the customer.
We then place our order with the print-on-demand service.

The print-on-demand service will periodically update us on the order status, which we can update our customers, but this would be a different business process. Let’s look at the order process first and imagine this was all done inline in one controller. It would get quite complicated to manage or change.

class PlaceOrderController

{

public function __invoke(PlaceOrderRequest $request): RedirectResponse

{

// Create our customer record.

$customer = Customer::query()->create([]);

 

// Create an order for our customer.

$order = $customer->orders()->create([]);

 

try {

// Use a payment library to take payment.

$payment = Stripe::charge($customer)->for($order);

} catch (Throwable $exception) {

// Handle the exception to let the customer know payment failed.

}

 

// Confirm the order and payment with the customer.

Mail::to($customer->email)->send(new OrderProcessed($customer, $order, $payment));

 

// Send the order to the Print-On-Demand service

MerchStore::create($order)->for($customer);

 

Session::put('status', 'Your order has been placed.');

 

return redirect()->back();

}

}

So if we walk through this code, we see that we create a user and order – then accept the payment and send an email. Finally, we add a status message to the session and redirect the customer.

So we write to the database twice, talk to the payment API, send an email, and finally, write to the session and redirect. It is quite a lot in one synchronous thread to handle, with a lot of potential for things to break. The logical step here is to move this to a background job so that we have a level of fault tolerance.

class PlaceOrderController

{

public function __invoke(PlaceOrderRequest $request): RedirectResponse

{

// Create our customer record.

$customer = Customer::query()->create([]);

 

dispatch(new PlaceOrder($customer, $request));

 

Session::put('status', 'Your order is being processed.');

 

return redirect()->back();

}

}

We have cleaned up our controller a lot – however, all we have done is move the problem to a background process. While moving this to a background process is the right way to handle this, we need to approach this a lot differently.

Firstly, we want to first or create the customer – in case they have made an order before.

class PlaceOrderController

{

public function __invoke(PlaceOrderRequest $request): RedirectResponse

{

// Create our customer record.

$customer = Customer::query()->firstOrCreate([], []);

 

dispatch(new PlaceOrder($customer, $request));

 

Session::put('status', 'Your order is being processed.');

 

return redirect()->back();

}

}

Our next step is to move the creation of a customer to a shared class – this is one of many times we would want to create or get a customer record.

class PlaceOrderController

{

public function __construct(

private readonly FirstOrCreateCustomer $action,

) {}

 

public function __invoke(PlaceOrderRequest $request): RedirectResponse

{

// Create our customer record.

$customer = $this->action->handle([]);

 

dispatch(new PlaceOrder($customer, $request));

 

Session::put('status', 'Your order is being processed.');

 

return redirect()->back();

}

}

Let’s look at the background process code if we moved it directly there.

class PlaceOrder implements ShouldQueue

{

use Dispatchable;

use InteractsWithQueue;

use Queueable;

use SerializesModels;

 

public function _construct(

public readonly Customer $customer,

public readonly Request $request,

) {}

 

public function handle(): void

{

// Create an order for our customer.

$order = $this->customer->orders()->create([]);

 

try {

// Use a payment library to take payment.

$payment = Stripe::charge($this->customer)->for($order);

} catch (Throwable $exception) {

// Handle the exception to let the customer know payment failed.

}

 

// Confirm the order and payment with the customer.

Mail::to($this->customer->email)

->send(new OrderProcessed($this->customer, $order, $payment));

 

// Send the order to the Print-On-Demand service

MerchStore::create($order)->for($this->customer);

}

}

Not too bad, but – what if a step fails and we retry the job? We will end up redoing parts of this process again and again when not needed. We should first look to create the order within a database transaction.

class CreateOrderForCustomer

{

public function handle(Customer $customer, data $payload): Model

{

return DB::transaction(

callback: static fn () => $customer->orders()->create(

attributes: $payload,

),

);

}

}

Now we can update our background process to implement this new command.

class PlaceOrder implements ShouldQueue

{

use Dispatchable;

use InteractsWithQueue;

use Queueable;

use SerializesModels;

 

public function _construct(

public readonly Customer $customer,

public readonly Request $request,

) {}

 

public function handle(CreateOrderForCustomer $command): void

{

// Create an order for our customer.

$order = $command->handle(

customer: $customer,

payload: $this->request->only([]),

);

 

try {

// Use a payment library to take payment.

$payment = Stripe::charge($this->customer)->for($order);

} catch (Throwable $exception) {

// Handle the exception to let the customer know payment failed.

}

 

// Confirm the order and payment with the customer.

Mail::to($this->customer->email)

->send(new OrderProcessed($this->customer, $order, $payment));

 

// Send the order to the Print-On-Demand service

MerchStore::create($order)->for($this->customer);

}

}

This approach works well. However, it isn’t ideal, and you do not have much visibility at any point. We could model this differently so that we are modeling our business process instead of splitting it out into parts.

It all starts with the Pipeline facade, enabling us to build this process correctly. We will still want to create our customer in the controller, but we will handle the rest of the process within the background job using a business process.

To begin with, we will need an abstract class that our business process classes can extend to minimize code duplication.

abstract class AbstractProcess

{

public array $tasks;

 

public function handle(object $payload): mixed

{

return Pipeline::send(

passable: $payload,

)->through(

pipes: $this->tasks,

)->thenReturn();

}

}

Our business process class will have many associated tasks, which we declare in the implementation. Then our abstract process will take the passed-on payload and send it through these tasks – eventually returning. Unfortunately, I can’t think of a nice way to return an actual type instead of mixed, but sometimes we have to compromise…

class PlaceNewOrderForCustomer extends AbstractProcess

{

public array $tasks = [

CreateNewOrderRecord::class,

ChargeCustomerForOrder::class,

SendConfirmationEmail::class,

SendOrderToStore::class,

];

}

As you can see, this is super clean to look at and works well. These tasks can be reused in other business processes where it makes sense.

class PlaceOrder implements ShouldQueue

{

use Dispatchable;

use InteractsWithQueue;

use Queueable;

use SerializesModels;

 

public function _construct(

public readonly Customer $customer,

public readonly Request $request,

) {}

 

public function handle(PlaceNewOrderForCustomer $process): void

{

try {

$process->handle(

payload: new NewOrderForCustomer(

customer: $this->customer->getKey(),

orderPayload: $this->request->only([]),

),

);

} catch (Throwable $exception) {

// Handle the potential exceptions that could occur.

}

}

}

Our background process now tries to handle the business process, and if any exceptions happen, we can fail and retry the process later on. As Laravel will use its DI container to pass through what you need into the jobs handle method, we can pass our process class into this method and let Laravel resolve this for us.

class CreateNewOrderRecord

{

public function __invoke(object $payload, Closure $next): mixed

{

$payload->order = DB::transaction(

callable: static fn () => Order::query()->create(

attributes: [

$payload->orderPayload,

'customer_id' $payload->customer,

],

),

);

 

return $next($payload);

}

}

Our business process tasks are invokable classes that get passed the “traveller”, which is the payload we want to pass through, and a Closure which is the next task in the pipeline. This is similar to how the middleware functionality works in Laravel, where we can chain on as many as we need, and they are just sequentially called.

The payload we pass in can be a simple PHP object we can use to build as it goes through a pipeline, extending it at each step, allowing the next task in the pipeline to access any information it needs without running a database query.

Using this approach, we can break down our business processes that aren’t digital and make digital representations of them. Chaining them together in this way adds automation where we need it. It is quite a simple approach, really, but it is very powerful.

Have you found a nice way to handle business processes in Laravel? What did you do? Let us know on twitter!

Laravel News

How to Configure Subdomain routes in Laravel for Domain Driven Design

https://twtv3.ams3.digitaloceanspaces.com/subdomain-routes-laravel.jpg

Also Read: Structure Laravel App for DDD 

Also Read: Routes in Laravel for DDD

If you need to access your routes based on subdomains like product.thewebtier.com/products. To achieve this, you need to modify your route definitions in Laravel and configure web server to handle subdomains.

Modify your route definitions

First, update your route definitions to use subdomain-based routing in the app/Domain/Product/routes/web.php or app/Domain/Product/routes/api.php file.

Also Read: Create own PHP Router

For example, in app/Domain/Product/routes/web.php:

<?php
use App\Domain\Product\Controllers\ProductController;
use Illuminate\Support\Facades\Route;
Route::domain('product.thewebtier.com')->group(function () {
    Route::get('/products', [ProductController::class, 'index'])->name('products.index');
    // Add other product routes here
});

Similarly, you can define routes for other domains in their respective route files.

Configure your Web Server

You need to configure your web server (e.g., Apache or Nginx) to handle subdomains and point them to your Laravel application.

Nginx configuration for DDD

Following example code will work for Nginx configuration for setting up subdomain routing for Laravel application in DDD.

server {
    listen 80;
    server_name product.thewebtier.com;
    root /path/to/laravel/public;
    index index.php index.html index.htm;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
    }
    location ~ /\.ht {
        deny all;
    }
}

Apache configuration for DDD

For Apache, create or modify the virtual host configuration:

<VirtualHost *:80>
    ServerName product.thewebtier.com
    DocumentRoot /path/to/laravel/public
    <Directory /path/to/laravel/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Make sure to replace /path/to/laravel with the actual path to your Laravel application.

Configure your DNS

Add a DNS record (A or CNAME) for the subdomain (product.thewebtier.com) and point it to your server’s IP address or domain.

Also Read: MySQL backups in Laravel

After completing these steps, you should be able to access your routes using the subdomain-based URL, like product.thewebtier.com/products.

Laravel News Links