Category Archives: PHP

Hands on creating a book store with Claude, for beginners, showing errors generated and fixing them easily

Claude AI hands on creating a Book e-Commerce and fixing errors, PHPStorm, PHP, Docker Desktop, MySQL in Windows

I’ll show the process of a creation of a web application for a e-Commerce book store.

The most important is to define a good requirements prompt.
I created a file named docs/promptia.md

Set the quality to the max in youtube to be able to see the screen clearly.

It takes long time, so unless you want to see all the process in real time, use the chapters I added to skip to the parts you’re interested.

Chapters in the youtube video:

00:00 Tell Claude to create a web app based on docs/promptia.md
18:29 Claude asks permission to run Powershell commands
19:02 Application created
19:37 Check in PHPStorm the promptia.md
19:51 Add to git and Commit with PHPStorm
20:27 Create and launch containers
20:50 Create the containers
20:54 Launch containers
21:10 Show in Docker Desktop
21:23 Display in logs entrypoint.sh
22:04 composer install
22:19 Error: missing composer require symfony/yaml
22:32 Asking Claude to fix the error
23:50 Destroy project to ensure it is build without errors (for later in Production)
24:28 Create destroy-project.bat
25:42 Re-creating the containers
25:52 Re-creating without cache
29:20 Containers launched in Docker Desktop
30:10 composer update
30:28 Checking engine container error in a .yaml in Claude Code
31:13 Error non-existent service “doctrine system cache pool”
31:34 Inside the engine container curl http://127.0.0.1 Http Error 500
31:44 composer dump-env dev
31:57 Error a non-empty secret is required Http Error 500
32:14 Showing Claude the error, so it fixes it
33:12 Check from the engine container curl http://127.0.0.1
33:42 Error could not find the driver
33:51 Asking Claud to fix the error
34:05 Finding the error in the logs
34:27 I ask Claude, to continue with the log entry, after it finishes
35:16 Claude fixes the first problem and starts analyzing the second
35:35 Claude finds and fixes the second problem (introduced by Claude before)
37:12 Creating the Database with the Command
37:32 A new curl, and a new error found (introduced by Claude before)
37:58 Requesting to Claude to fix the error
38:25 Claude fixes the error
38:30 The new website loads correctly
39:00 Viewing register form (needs work)
39:05 Request a script to enter to mysql via CLI
40:02 I open the new script login_to_mysql.sh in PHPStorm
40:23 Trying the CLI Command to init the Database Schema
40:39 Giving chmod +x from Docker (for commiting to the repo)
40:45 login_to_mysql.sh fails (due an error introduced by Claude before)
40:58 finding extension=pdo_mysql in php.ini on the container duplicated
41:10 Asking Claude to remove the error
41:37 Claude realizes the error
41:45 Logged to MySQL with the script
42:05 DESC orders;
42:18 Asking Claude a refactor or prices from DECIMAL to Integers
43:53 Ask next questions while Claude is still working
46:56 Update the Command to reflect the new field changes
48:00 Copy the ALTER TABLE
48:05 Execute in the MySQL in Docker Desktop
48:12 Schema updated in docs/scheme.md
48:18 Add a field “public_name”
48:58 Update MySQL with the ALTER

My very first time installing Claude Code and using it

I install Claude Code for the very first time, I use a voucher provided from a friend to use it 7 days for free with the USD $18 / month, although there is a Free Subscription you can use.

I donwload and install it on Windows 11 and I start to used it immediately with an incipient Symfony PHP Docker nginx Linux project.

I show you how I combine it with PHPStorm, how I use the Working Tree and the Pull Request (PR) and the problems I find when I request functionalities.

Video showing how to start with JetBrain’s Junie IA agent

A video as an introduction to Junie, showing the creation of a web project from zero, with Junie IA agent.

The subscription I used is $20 USD per month.

A Symfony 7.4 with PHP 8.5 in a Docker Container with Ubuntu 26.04 LTS is requested.

Junie creates the solution with Ubuntu 24.04 LTS and Symfony 7.1 and PHP 8.3, so I instruct it to fix it.

The video shows some errors created by the agent, and how to make it correct them.

Vibe coding with Google Antigravity, new features, to a project, in real time

This video shows real example of my workflow, in real time, on how I programmed with Google Antigravity some new features, like adding discount coupons, for my commercial web project for quickly audio conversion https://audioconverter.carlesmateo.com/

I show some problems when working with Gemini 3 Flash, and how I instructed the IA to fix them.

Solving silent exit error on eZ Launchpad

You have installed eZ Launchpad, and you can execute the binary ez from your home folder or other paths, however when you execute it from a project folder you cloned with git (with its .platform.app.yaml file) ez returns to prompt without any error message.

The exit code is 255, but even if you strace the process you don’t find the exact problem.

Inside your project you run ez without any argument in a clean install of Ubuntu 24.04 LTS with PHP 8.3, or with PHP 8.4, without xDebug, without opcache, without memory limit… nothing works with no visible error message in the logs or in the error output. However if you run it outside the project folder, it works, and it displays the typical help messages.

I reproduced this behavior on several Ubuntu computers. The fix I found is to execute ez with PHP 8.1

You can install PHP8.1 from ondrej repository, then you can update alternates to execute PHP 8.1 by default in your system, or you create the project by invoking ez with PHP 8.1 explicitly with:

php8.1 ~/ez create

This will kickstart the creation of your ez project based on Docker containers.

Installing PHP environment for development in Windows

This article is for my students learning PHP, or for any student that wants to learn PHP and uses a Windows computer for that.

For this we will install:

XAMPP, which is available for Windows, Mac OS and Linux.

You can download it from: https://www.apachefriends.org/

XAMPP installs together:

  • Apache
  • MariaDB
  • PHP
  • Perl

Install WAMPP instead of XAMP (if you prefer WAMPP)

Alternatively you can install WAMPP, which installs:

  • Apache
  • MySQL
  • PHP
  • PHPMyAdmin

https://www.wampserver.com/en/

Development IDE

As Development Environment we will use PHPStorm, from Jetbrains.

https://www.jetbrains.com/phpstorm/

Testing the installation of XAMPP

The default directory for the PHP files is C:\xampp\htdocs

Create a file in c:\xampp\htdocs named hello.php

<?php
$s_today = date("Y-m-d");
echo "Hello! Today is ".$s_today;
?>

Now start Apache:

  1. Open the XAMPP Control Panel
  2. Start the Apache Server
You should see at least port 80 for Apache

And test the new page, with the browser, opening:

http://localhost/hello.php

Video: How to create a Docker Container for LAMPP step by step

How to create a Docker Container for Linux Apache MySQL PHP and Python for beginners.

Note: Containers are not persistent. Use this for tests only. If you want to keep persistent information use Volumes.

Sources: https://gitlab.com/carles.mateo/blog.carlesmateo.com-source-code/-/tree/master/twitch/live_20220708_dockerfile_lamp

File: Dockerfile

FROM ubuntu:20.04

MAINTAINER Carles Mateo

ARG DEBIAN_FRONTEND=noninteractive

RUN apt update && \
    apt install -y vim python3-pip &&  \
    apt install -y net-tools mc vim htop less strace zip gzip lynx && \
    apt install -y apache2 mysql-server ntpdate libapache2-mod-php7.4 mysql-server php7.4-mysql php-dev libmcrypt-dev php-pear && \
    apt install -y git && apt autoremove && apt clean && \
    pip3 install pytest

RUN a2enmod rewrite

RUN echo "Europe/Ireland" | tee /etc/timezone

ENV APACHE_RUN_USER  www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR   /var/log/apache2
ENV APACHE_PID_FILE  /var/run/apache2/apache2.pid
ENV APACHE_RUN_DIR   /var/run/apache2
ENV APACHE_LOCK_DIR  /var/lock/apache2
ENV APACHE_LOG_DIR   /var/log/apache2

COPY phpinfo.php /var/www/html/

RUN service apache2 restart

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

File: phpinfo.php

<html>
<?php

// Show all information, defaults to INFO_ALL
phpinfo();

// Show just the module information.
// phpinfo(8) yields identical results.
phpinfo(INFO_MODULES);
?>
</html>

File: build_docker.sh

#!/bin/bash

s_DOCKER_IMAGE_NAME="lampp"

echo "We will build the Docker Image and name it: ${s_DOCKER_IMAGE_NAME}"
echo "After, we will be able to run a Docker Container based on it."

printf "Removing old image %s\n" "${s_DOCKER_IMAGE_NAME}"
sudo docker rm "${s_DOCKER_IMAGE_NAME}"

printf "Creating Docker Image %s\n" "${s_DOCKER_IMAGE_NAME}"
# sudo docker build -t ${s_DOCKER_IMAGE_NAME} . --no-cache
sudo docker build -t ${s_DOCKER_IMAGE_NAME} .

i_EXIT_CODE=$?
if [ $i_EXIT_CODE -ne 0 ]; then
    printf "Error. Exit code %s\n" ${i_EXIT_CODE}
    exit
fi

echo "Ready to run ${s_DOCKER_IMAGE_NAME} Docker Container"
echo "To run in type: sudo docker run -p 80:80 --name ${s_DOCKER_IMAGE_NAME} ${s_DOCKER_IMAGE_NAME}"
echo "or just use run_in_docker.sh"

echo
echo "If you want to debug do:"
echo "docker exec -i -t ${s_DOCKER_IMAGE_NAME} /bin/bash"

Why I think in Python is not a good idea to raise exceptions inside your methods

Last update: 2022-05-18 10:48 Irish Time

Recently a colleague was asking me for advice on their design of error handling in a Python application.

They were catching an error and raising an Exception, inside the except part of a method, to be catch outside the method.

And at some point a simple logic got really messy and unnecessarily complicated. Also troubleshooting and debugging an error was painful because they were only getting a Custom Exception and not context.

I explained to my colleague that I believed that the person that created that Exception chain of catch came from Java background and why I think they choose that path, and why I think in Python it’s a bad idea.

In Java, functions and methods can only return one object.

I programmed a lot in Java in my career, and it was a pain having to create value objects, and having to create all kind of objects for the return. Is it a good thing that types are strongly verified by the language? Yes. It worked? Yes. It made me invest much more time than necessary? Also yes.

Having the possibility to return only one object makes it mandatory having a way to return when there was an error. Otherwise you would need to encapsulate an error code and error description fields in each object, which is contrary to the nature of the object.

For example, a class Persona. Doesn’t make any sense having an attribute inside the class Persona to register if an operation related to this object went wrong.

For example, if we are in a class Spaceship that has a method GetPersonaInCommand() and there is a problem in that method, doesn’t make any sense to return an empty Persona object with attributes idError, errorDescription. Probably the Constructor or Persona will require at least a name or Id to build the object…. so in this case, makes sense that the method raises an Exception so the calling code catches it and knows that something went wrong or when there is no data to return.

This will force to write Custom Exceptions, but it’s a solution.

Another solution is creating a generic response object which could be an Object with these attributes:

  • idError
  • errorDescription
  • an Object which is the response, in our example Persona or null

I created this kind of approach for my Cassandra libraries to easily work with Cassandra from Java and from PHP, and for Cassandra Universal Driver (a http/s gateway created in year 2014).

Why this in not necessary in Python

Python allows you to return multiple values, so I encourage you tor return a boolean for indicating the success of the operation, and the object/value you’re interested.

You can see it easily if you take a look to FileUtils class from my OpenSource libraries carleslibs.

The method get_file_size_in_bytes(self, s_file) for example:

    def get_file_size_in_bytes(self, s_file):

        b_success = False
        i_file_size = 0

        try:
            # This will help with Unit Testing by raisin IOError Exception
            self.test_helper()

            i_file_size = os.path.getsize(s_file)
            b_success = True
        except IOError:
            b_success = False

        return b_success, i_file_size

It will always return a boolean value to indicate success or failure of the operation and an integer for the size of the file.

The calling code will do something like this:

o_fileutils = FileUtils()
b_success, i_bytes = o_fileutils.get_file_size_in_bytes("profile.png")
if b_succes is False:
    print("Error! The file does not exist or cannot be accessed!")
    exit(1)

if i_bytes < 1024:
    print("The profile picture should be at least 1KB")
    exit(1)

print("Profile picture exists and is", i_bytes, " bytes in length!")

The fact that Python can return multiple variables makes super easy dealing with error handling without having to take the road of Custom Exceptions.

And it is Ok if you want to follow this path, but in my opinion, for most of the developers up to Senior levels, it only over complicates the logic of your code and the amount of try/excepts you have to have everywhere.

If you use PHP you can mix different types in an Array, so you can always return an Array with a boolean, or an i_id_error, and your object or data of whatever type it’s.

Getting back to my carleslibs Open Source package, it is super easy to Unit Test these methods.

In my opinion, this level of simplicity, brings only advantages. Including Software Development speed, which is good for the business.

I’m not advocating for not using Custom Exceptions or to not develop a Exceptions Raising strategy if you need it and you know what you’re doing. I’m just suggesting why I think most of the developments in Python do not really need this and only over complicates the development. There are situations where raising exceptions will be a perfectly useful or even the best approach, there are many scenarios, but I think that in most of cases, using raise inside except will only multiply the time of the development and slow down the speed of bringing new features to the business, over complicating Unit Test as well, and be a real pain for the Junior and Intermediate developers.

The Constructor

Obviously, as the Constructor doesn’t return any value, it is perfectly fine to raise an exception in there, or just to use try/except in the code that is instancing the objects.

News from the blog 2022-04-22

Media/Press

I was interviewed by Radio America Barcelona, in their studios in Barcelona.

RAB is a radio for the Catalan diaspora and expats.

The interview was broadcasted by Twitch and can be watched. It’s in Catalan language:

https://www.twitch.tv/videos/1448895585

You can follow them:

Sant Jordi discounted books (promo)

Tomorrow 23th of April is Sant Jordi (Saint George), the patron of Catalonia, and the Catalan traditional celebration consist in this day women gifting a book to the men they love and men gifting a rose to the women they love.

I created a voucher for all my Python books, so, since during 23th of April you can acquire the four books per $10 USD in total.

This voucher is limited to 100 sales.

https://leanpub.com/b/python3all/c/SANTJORDI2022

Python 3

I wrote an article with a Python 3 code that shows the length for file names in Linux ext3 and ext4 Filesystems and in ZFS Pools Filesystem.

I show basically how ASCii characters over 127 are encoded, reducing the maximum length of 255 bytes for the filename.

ZFS

I’ve updated an article explaining how to create a ZPool raidz (RAID 5 equivalent) from three loop devices based on local files.

Thanks to those that bought my ZFS book this month. :)

HTML and JavaScript

I wrote a super simple code to hide the <p> using jQuery and JavaScript.

Free books

https://books.goalkicker.com/

Books I bought

This month I bought these books.

Firewall

I continued to block any Russian or Belarus Ip Address that connects to the blog.

I also started to block entire ranges of Ip’s from Digital Ocean, as many attacks come from Servers in their infrastructure.

Despite blocking tens of thousands of Ip Addresses, the number of visitors keep growing.

My Health

Thanks to my strict discipline I managed to recover super well and I’m healthier than before and guided by the satisfied doctors we removed two daily medicines.

I started a new medicine that is for the final phase of my recuperation, which doctors expect to be completely. In fact I’m much more healthier than I was before going to the hospital.

Humor

Will AI take the world?
Sadly, true history. The responsibility to deliver is from all of us.