<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nao</title>
    <description>The latest articles on DEV Community by Nao (@hanaosan).</description>
    <link>https://dev.to/hanaosan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1757368%2F3ffd3a4d-496f-424f-a4cc-546f52e14924.png</url>
      <title>DEV Community: Nao</title>
      <link>https://dev.to/hanaosan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hanaosan"/>
    <language>en</language>
    <item>
      <title>[PHP] Upgrading from PHP 7.4 to 8.1🐘✨</title>
      <dc:creator>Nao</dc:creator>
      <pubDate>Fri, 30 May 2025 14:30:28 +0000</pubDate>
      <link>https://dev.to/hanaosan/php-upgrading-from-php-74-to-81-3ffk</link>
      <guid>https://dev.to/hanaosan/php-upgrading-from-php-74-to-81-3ffk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I upgraded my project’s PHP version from 7.4 to 8.1.&lt;/p&gt;

&lt;p&gt;This article summarizes the steps I took and the considerations I encountered during the upgrade process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Article Covers
&lt;/h2&gt;

&lt;p&gt;Upgrading PHP from version 7.4 to 8.1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Using EC2

&lt;ul&gt;
&lt;li&gt;OS Image: Amazon Linux 2 Kernel 5.10&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;PHP Version: PHP 7.4.33 (cli)&lt;/li&gt;

&lt;li&gt;PHPUnit Version: 9.5.28&lt;/li&gt;

&lt;li&gt;CakePHP Version: 4.2.12&lt;/li&gt;

&lt;li&gt;nginx: nginx/1.22.0&lt;/li&gt;

&lt;li&gt;php-fpm: PHP 7.4.33 (fpm-fcgi)&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Gathering Upgrade Information
&lt;/h3&gt;

&lt;h4&gt;
  
  
  PHP
&lt;/h4&gt;

&lt;p&gt;Each PHP version is supported for three years (2 years active support + 1 year security support).&lt;br&gt;
Since support for PHP 7.4 ended on November 28, 2022, I decided to upgrade to PHP 8.1 to ensure continued maintainability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.php.net/supported-versions.php" rel="noopener noreferrer"&gt;PHP Supported Versions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I reviewed the official documentation for breaking changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/migration80.php" rel="noopener noreferrer"&gt;Migrating from PHP 7.4.x to PHP 8.0.x&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/migration81.php" rel="noopener noreferrer"&gt;Migrating from PHP 8.0.x to PHP 8.1.x&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  PHPUnit
&lt;/h4&gt;

&lt;p&gt;As I was using PHPUnit for testing code, I also checked compatibility between PHP and PHPUnit.&lt;/p&gt;

&lt;p&gt;I checked the current PHPUnit version with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./vendor/bin/phpunit --version

PHPUnit 9.5.28 by Sebastian Bergmann and contributors.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;According to the PHPUnit and PHP version compatibility chart, PHPUnit 9.x supports PHP 7.3 and above.&lt;br&gt;
Since I'm upgrading to PHP 8.1, our current version (9.5.28) remains compatible.&lt;/p&gt;
&lt;h4&gt;
  
  
  CakePHP
&lt;/h4&gt;

&lt;p&gt;Next, I checked compatibility between CakePHP and PHP.&lt;/p&gt;

&lt;p&gt;I confirmed the current CakePHP version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat ./vendor/cakephp/cakephp/VERSION.txt
...
4.2.12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the CakePHP 4 System Requirements, CakePHP 4 supports PHP 7.4 and higher, including PHP 8.1. So there are no issues here either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing a Test Environment
&lt;/h2&gt;

&lt;p&gt;Since the service was already deployed, I needed to verify if the upgrade would succeed and ensure functionality post-upgrade in a separate environment.&lt;/p&gt;

&lt;p&gt;I used another EC2 instance to test the upgrade to PHP 8.1, ran the test code, confirmed stable behavior, and then proceeded with the production upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to Upgrade to PHP 8.1
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Back up the php.ini file (PHP configuration file).
&lt;/h3&gt;

&lt;p&gt;First, locate php.ini:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ find / -name "php.ini" -ls

8651969   64 -rw-r--r--   1 root     root        62221  Jan 21 03:18 /etc/php.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a backup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cp -a /etc/php.ini /etc/php.ini.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a custom version of php.ini, back that up as well.&lt;/p&gt;

&lt;p&gt;Check the current PHP version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php -v

PHP 7.4.33 (cli) (built: Nov 19 2022 00:22:13) ( NTS )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List installed PHP packages to reinstall them later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yum list installed php*

Installed Packages:
php-cli.x86_64, php-common.x86_64, php-fpm.x86_64, php-intl.x86_64, php-json.x86_64,
php-mbstring.x86_64, php-mysqlnd.x86_64, php-pdo.x86_64, php-xml.x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove current PHP packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yum remove "php*"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check available PHP versions via Amazon Linux Extras:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ amazon-linux-extras list available | grep php

42 *php7.4=latest            enabled      [ =stable ]
_  php8.0                   available    [ =stable ]
_  php8.1                   available    [ =stable ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disable PHP 7.4:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ amazon-linux-extras disable php7.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install PHP 8.1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ amazon-linux-extras install php8.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify installed PHP packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yum list installed php*

Installed Packages:
php-cli.x86_64, php-common.x86_64, php-fpm.x86_64, php-mysqlnd.x86_64, php-pdo.x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install any missing packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yum install php-intl php-json php-mbstring php-xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm PHP version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php -v

PHP 8.1.14 (cli) (built: Jan 20 2023 18:11:30) (NTS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart nginx and php-fpm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ systemctl restart nginx php-fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The upgrade is complete!&lt;/p&gt;

&lt;p&gt;Now run the test code and verify behavior through the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Through this upgrade, I learned the importance of checking compatibility with related packages and frameworks like PHPUnit and CakePHP.&lt;/p&gt;

&lt;p&gt;While I relied on reading documentation and running tests to identify incompatibilities, in the future, I’d like to try static analysis tools for migration checks (see: &lt;a href="https://www.bit-hive.com/articles/20230126" rel="noopener noreferrer"&gt;PHP8 Migration Compatibility Check&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts or feedback!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP 8.1 Upgrade Steps:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/amazon-linux-2/faqs/?nc1=h_ls#topic-0" rel="noopener noreferrer"&gt;Amazon Linux 2 FAQs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qiita.com/hisatoo/items/d445e831995d82dfe4ab" rel="noopener noreferrer"&gt;Upgrading PHP on Amazon Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>php</category>
      <category>upgrade</category>
    </item>
    <item>
      <title>[GitHub Actions] Automate Build and Deployment of Your Python Package to PyPI and GitHub Releases 🐍📦</title>
      <dc:creator>Nao</dc:creator>
      <pubDate>Sat, 10 Aug 2024 04:26:48 +0000</pubDate>
      <link>https://dev.to/hanaosan/github-actions-automate-build-and-deployment-of-your-python-package-to-pypi-and-github-releases-51hj</link>
      <guid>https://dev.to/hanaosan/github-actions-automate-build-and-deployment-of-your-python-package-to-pypi-and-github-releases-51hj</guid>
      <description>&lt;p&gt;When releasing a custom library, it can be tedious to manually build it locally, upload it to TestPyPI for verification, then upload it to PyPI, and finally tag and release it… &lt;/p&gt;

&lt;p&gt;So, I decided to automate the deployment using GitHub Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objective of This Article
&lt;/h2&gt;

&lt;p&gt;When you push a tag to the remote repository, this setup will automatically upload your package to PyPI and create a GitHub release.&lt;/p&gt;

&lt;p&gt;After you push a tag from your local environment…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git tag vX.X.X
git push origin vX.X.X
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following steps will be automatically executed in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload to TestPyPI&lt;/li&gt;
&lt;li&gt;Upload to PyPI&lt;/li&gt;
&lt;li&gt;Create a release on GitHub and distribute the source code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will create a workflow as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjld14qk1g813xj5f3pj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjld14qk1g813xj5f3pj.png" alt="workflow" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;Note: Instead of using setup.py as the packaging tool configuration file, we will use pyproject.toml. According to PEP-518, pyproject.toml is recommended for modern Python projects.&lt;/p&gt;

&lt;p&gt;Prepare your Python package and upload it as a project to both PyPI and TestPyPI.&lt;/p&gt;

&lt;p&gt;If you already have a custom library on PyPI, you can skip this step.&lt;/p&gt;

&lt;p&gt;Follow the tutorial below to upload a sample package to TestPyPI and PyPI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://packaging.python.org/ja/latest/tutorials/packaging-projects/#creating-a-license" rel="noopener noreferrer"&gt;https://packaging.python.org/ja/latest/tutorials/packaging-projects/#creating-a-license&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Workflow File in GitHub Actions
&lt;/h3&gt;

&lt;p&gt;In your repository, go to &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Set up a workflow yourself&lt;/code&gt; &amp;gt; Create a YAML file with any name (in this case, main.yaml) and commit it. &lt;/p&gt;

&lt;p&gt;It’s okay if the file is empty initially.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Publishing in PyPI
&lt;/h3&gt;

&lt;p&gt;Traditionally, to upload a package from GitHub Actions to PyPI, you would need to create an API token in PyPI and store that token as a secret in GitHub.&lt;/p&gt;

&lt;p&gt;However, by using Publishing, you can automatically issue and authenticate a temporary token when connecting to pre-configured services (including specific users, repositories, etc.)!&lt;/p&gt;

&lt;p&gt;Publishing is easier to set up, and since the token has a short expiration time, it also offers better security.&lt;/p&gt;

&lt;p&gt;From your project page on PyPI, select &lt;code&gt;Publishing&lt;/code&gt; &amp;gt; &lt;code&gt;Add a new publisher&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fill in the fields as shown in the image below and click &lt;code&gt;Add&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy6pozpd3vk14npznnae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy6pozpd3vk14npznnae.png" alt="Publishing for PyPI" width="800" height="794"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, open TestPyPI and create a publisher in the same way.&lt;/p&gt;

&lt;p&gt;Use a different environment name than the one used for PyPI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furczm3z02orkp073wc3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furczm3z02orkp073wc3m.png" alt="Publishing for TestPyPI" width="800" height="774"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow in GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Now let’s write the workflow in the YAML file you just created.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Start the Workflow When a Tag is Pushed
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish Python 🐍 distribution 📦 to PyPI and TestPyPI&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v*.*.*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Build
&lt;/h4&gt;

&lt;p&gt;To build the package, pyproject.toml must exist in the repository, so make sure it is not included in .gitignore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build distribution 📦&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt; &lt;span class="c1"&gt;# Checkout the code&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v5&lt;/span&gt; &lt;span class="c1"&gt;# Set up the Python environment&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.x"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install pypa/build&lt;/span&gt; &lt;span class="c1"&gt;# Install the build tool&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
        &lt;span class="s"&gt;python3 -m&lt;/span&gt;
        &lt;span class="s"&gt;pip install&lt;/span&gt;
        &lt;span class="s"&gt;build&lt;/span&gt;
        &lt;span class="s"&gt;--user&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build a binary wheel and a source tarball&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3 -m build&lt;/span&gt; &lt;span class="c1"&gt;# Build the package&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Store the distribution packages&lt;/span&gt; &lt;span class="c1"&gt;# Temporarily store the build artifacts in the dist directory under the name python-package-distributions&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python-package-distributions&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dist/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Publish to TestPyPI
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;publish-to-testpypi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish Python 🐍 distribution 📦 to TestPyPI&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt; &lt;span class="c1"&gt;# Start the job only if the build job has completed&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;testpypi&lt;/span&gt; &lt;span class="c1"&gt;# Enter the environment name set in the Publisher&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://test.pypi.org/p/example-package-hanaosan0318&lt;/span&gt; &lt;span class="c1"&gt;# Project URL&lt;/span&gt;

    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;  &lt;span class="c1"&gt;# Grant Publishing permissions&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download all the dists&lt;/span&gt; &lt;span class="c1"&gt;# Download the build artifacts that were saved earlier&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/download-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python-package-distributions&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dist/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish distribution 📦 to TestPyPI&lt;/span&gt; &lt;span class="c1"&gt;# Publish to TestPyPI&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pypa/gh-action-pypi-publish@release/v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;repository-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://test.pypi.org/legacy/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Publish to PyPI
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;publish-to-pypi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;Publish Python 🐍 distribution 📦 to PyPI&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;publish-to-testpypi&lt;/span&gt; &lt;span class="c1"&gt;# Start the job only if the TestPyPI publishing job has completed&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pypi&lt;/span&gt; &lt;span class="c1"&gt;# Enter the environment name set in the Publisher&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://pypi.org/p/example-package-hanaosan0318&lt;/span&gt; &lt;span class="c1"&gt;# Project URL&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download all the dists&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/download-artifact@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python-package-distributions&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dist/&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish distribution 📦 to PyPI&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pypa/gh-action-pypi-publish@release/v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Create a GitHub Release
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;github-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;Create GitHub Release with source code&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;publish-to-pypi&lt;/span&gt; &lt;span class="c1"&gt;# Start the job only if the PyPI publishing job has completed&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# Grant permission to create a GitHub release&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt; &lt;span class="c1"&gt;# Checkout the code&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create GitHub Release&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt; &lt;span class="c1"&gt;# A temporary token that is automatically generated each time the workflow is run&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
        &lt;span class="s"&gt;gh release create&lt;/span&gt;
        &lt;span class="s"&gt;'${{ github.ref_name }}'&lt;/span&gt;
        &lt;span class="s"&gt;--repo '${{ github.repository }}'&lt;/span&gt;
        &lt;span class="s"&gt;--notes "Release for version ${{ github.ref_name }}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you have defined the workflow!&lt;/p&gt;

&lt;p&gt;You can view the entire YAML file at the following link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hanaosan/ci-cd-practice-python-library/blob/main/.github/workflows/main.yml" rel="noopener noreferrer"&gt;https://github.com/hanaosan/ci-cd-practice-python-library/blob/main/.github/workflows/main.yml&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying
&lt;/h3&gt;

&lt;p&gt;Update the version in pyproject.toml to the release version and push the changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[project]
name = "example_package_hanaosan0318"
version = "2.0.3" # Change to the release version
authors = [
  { name="Example Author", email="author@example.com" },
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a tag and push it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git tag v2.0.3
git push origin v2.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package will be uploaded to PyPI and TestPyPI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgted1dh9a1df0e0xmsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgted1dh9a1df0e0xmsp.png" alt="PyPI" width="800" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A release will also be created, and you can see the source code distributed in zip and tar.gz formats.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzliwm29yyrfo9hycdm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzliwm29yyrfo9hycdm7.png" alt="release" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it! &lt;/p&gt;

&lt;p&gt;You have now automated the process of uploading your package to PyPI and creating a release on GitHub when you push a tag to the remote repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/hanaosan/ci-cd-practice-python-library" rel="noopener noreferrer"&gt;https://github.com/hanaosan/ci-cd-practice-python-library&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows" rel="noopener noreferrer"&gt;Publishing package distribution releases using GitHub Actions CI/CD workflows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>pypi</category>
      <category>cicd</category>
      <category>python</category>
    </item>
    <item>
      <title>How to connect DynamoDB with CakePHP4</title>
      <dc:creator>Nao</dc:creator>
      <pubDate>Wed, 10 Jul 2024 16:08:33 +0000</pubDate>
      <link>https://dev.to/hanaosan/referencing-dynamodb-with-cakephp4-2no6</link>
      <guid>https://dev.to/hanaosan/referencing-dynamodb-with-cakephp4-2no6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When using DynamoDB, I struggled with connecting CakePHP and DynamoDB due to outdated articles and the need to create many files. Therefore, I wrote this article as a memo.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We'll Do in This Article
&lt;/h2&gt;

&lt;p&gt;We will connect to DynamoDB using CakePHP4 and retrieve table information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Using EC2

&lt;ul&gt;
&lt;li&gt;OS Image: Amazon Linux 2 Kernel 5.10&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;CakePHP Version: 4.2.12&lt;/li&gt;

&lt;li&gt;nginx: nginx/1.22.0&lt;/li&gt;

&lt;li&gt;PHP Version: PHP 7.4.33 (cli)&lt;/li&gt;

&lt;li&gt;PHP-FPM: PHP 7.4.33 (fpm-fcgi)&lt;/li&gt;

&lt;li&gt;AWS SDK for PHP Version: 3.257&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparation on AWS Side
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating a Table in DynamoDB
&lt;/h3&gt;

&lt;p&gt;Create an appropriate table from AWS Console Home &amp;gt; DynamoDB &amp;gt; Tables &amp;gt; Create Table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing AWS SDK
&lt;/h3&gt;

&lt;p&gt;While operations with AWS were done using the web console, the AWS SDK is necessary to use various services on AWS from a program.&lt;/p&gt;

&lt;p&gt;The AWS SDK is a development kit (a set of APIs and libraries necessary for development) provided for different programming languages to operate AWS services from a program.&lt;/p&gt;

&lt;p&gt;This time, we'll use the AWS SDK for PHP.&lt;br&gt;
Install it using composer. (&lt;a href="https://getcomposer.org/download/" rel="noopener noreferrer"&gt;Install Composer&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;project_base_directory
composer require aws/aws-sdk-php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the aws directory is created within /vendor, the installation is successful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an IAM Role
&lt;/h3&gt;

&lt;p&gt;Like entering a password to log in from the console, authentication information is needed when accessing resources on AWS from a program.&lt;/p&gt;

&lt;p&gt;Obtain the AWS access key as authentication information.&lt;/p&gt;

&lt;p&gt;There are three ways to obtain the access key depending on the user type and authentication method. (Reference: &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SettingUp.DynamoWebService.html" rel="noopener noreferrer"&gt;Obtaining AWS Access Keys&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If accessing AWS as an IAM user, there are two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Obtain the access key directly from the IAM user (long-term credentials) ← AWS not recommended&lt;/li&gt;
&lt;li&gt;Create an IAM role and link it to the EC2 instance. Automatically obtain temporary credentials each time you access (short-term credentials)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This time, we adopted the method of sending requests to AWS using temporary credentials by utilizing an IAM role.&lt;/p&gt;

&lt;p&gt;Create an IAM role with a policy that allows access to DynamoDB.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IAM &amp;gt; Roles &amp;gt; Create Role&lt;/li&gt;
&lt;li&gt;Trusted Entity Type

&lt;ul&gt;
&lt;li&gt;AWS Service&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Use Case

&lt;ul&gt;
&lt;li&gt;EC2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Permission Policy

&lt;ul&gt;
&lt;li&gt;AmazonDynamoDBFullAccess&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Role Name

&lt;ul&gt;
&lt;li&gt;role_test&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Link the created IAM role to the EC2 instance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 &amp;gt; Select Instance &amp;gt; Actions &amp;gt; Security &amp;gt; Modify IAM Role&lt;/li&gt;
&lt;li&gt;Select role_test and "Update IAM Role"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparation on the PHP Side
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Instantiate Client Object
&lt;/h3&gt;

&lt;p&gt;To operate the database on DynamoDB, instantiate the client object (this time DynamoDB object).&lt;/p&gt;

&lt;p&gt;The client object contains methods for executing the service's API.&lt;/p&gt;

&lt;p&gt;To instantiate, pass the configuration options as an associative array to the constructor (a method executed when the class is generated).&lt;/p&gt;

&lt;p&gt;Although you can directly instantiate the client object as shown below, this time, we instantiate the Sdk class → then instantiate DynamoDB.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Create an S3Client&lt;/span&gt;
&lt;span class="nv"&gt;$s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Aws\S3\S3Client&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'version'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'latest'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'region'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'us-east-2'&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By passing the associative array of options to the Sdk class, it can be used as a common set of configuration options for multiple clients.&lt;/p&gt;

&lt;p&gt;This time, I used only DynamoDB, but if you want to use other AWS services like S3 at the same time, it's convenient as you don't need to write the configuration options each time.&lt;/p&gt;

&lt;p&gt;Although only &lt;code&gt;region&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt; values are set in the associative array of options, the access key is also referenced when the client object is generated, as the EC2 instance linked to the IAM role created earlier obtains temporary credentials.&lt;/p&gt;

&lt;p&gt;This time, I created and described files under the plugin directory.&lt;/p&gt;

&lt;h4&gt;
  
  
  plugins/aws/Client/aws.php
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;aws\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aws&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Aws\DynamoDb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Cake\Core\Configure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Common AWS Class
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AwsClient&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$_sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$_dynamodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Constructor
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_sdk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Aws\Sdk&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'region'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'ap-northeast-1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'version'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'latest'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get DynamoDB Client
     *
     * @return $this-&amp;gt;dynamodb DynamoDbClient
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getDynamoDbClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_dynamodb&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_dynamodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_sdk&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createDynamoDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_dynamodb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  plugins/aws/DynamoDb.php
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;aws\Client\AwsClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Util\StrictComparison&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * DynamoDB Interface
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DynamoDb&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Constructor
     *
     * @param \Aws\Client\AwsClient $awsClient AwsClient Object
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AwsClient&lt;/span&gt; &lt;span class="nv"&gt;$awsClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StrictComparison&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;isNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$awsClient&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$awsClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AwsClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$awsClient&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDynamoDbClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get record by key name
     * 
     * @param string $tableName Table name
     * @param array $key Primary key
     * @return object Matching record
    */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getItemByKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'Key'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'TableName'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Retrieve Table Information
&lt;/h3&gt;

&lt;p&gt;With the necessary processes to connect to DynamoDB written, finally, instantiate the DynamoDB class in the Controller and retrieve the record by the specified key value.&lt;/p&gt;

&lt;h4&gt;
  
  
  src/Controller/DynamoDbController.php
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Cake\Controller\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;aws\DynamoDb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DynamoDbController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$tableName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'created_table_name'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'key_name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'S'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'value_to_search'&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$dynamoDb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DynamoDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$dynamoDb&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getItemByKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Pass the value of $result to the template so that the obtained content can be used on the view side.&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'result'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to confirm that the target record is obtained by checking the result with var_dump, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Using this procedure, it seems possible to connect not only to DynamoDB but also to other AWS services.&lt;/p&gt;

&lt;p&gt;Personally, it was very educational as I had only used Composer for loading packages, and now I know it is also necessary to use it when loading class files.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Creating IAM Roles

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html" rel="noopener noreferrer"&gt;Using temporary credentials with AWS resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Setting Namespace

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://qiita.com/atwata/items/5ba72d3d881a81227c2a" rel="noopener noreferrer"&gt;PHP Autoload (autoload)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Instantiating Client Object

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_basic-usage.html" rel="noopener noreferrer"&gt;Creating a Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Retrieving Table Information

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.ReadItem.html" rel="noopener noreferrer"&gt;Read items from a DynamoDB table using the AWS SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>dynamodb</category>
      <category>cakephp</category>
      <category>aws</category>
      <category>awssdk</category>
    </item>
  </channel>
</rss>
