Questions and solutions relating primarily to web page development. I have been developing web pages since 1994. I hope my articles will be helpful to you.
As a developer, I have had the opportunity to migrate several ordinary procedural PHP page websites into Laravel, a popular PHP framework. One of the key benefits of using Laravel is its seamless integration with Vite, a modern development server and build tool. Vite helps to build and manage CSS and JavaScript artifacts, making it easier to develop and maintain large web applications.
However, when migrating a website, it's often desirable to do so in stages, which can lead to a dilemma about how to manage CSS and JS artifacts between the new and old code. This can be further complicated by the fact that most older code runs JavaScript in the global scope, whereas Vite artifacts are generally used in the module scope. In this blog post, we'll explore how to bridge the gap between these two different approaches and leverage the advantages of using NPM to manage JavaScript versions and Vite to process CSS and JavaScript.
Understanding Global and Module Scopes in JavaScript
When including JavaScript on a page, it's important to understand the difference between loading a script normally versus as an ES module, since each behaves differently in terms of scope and import/export capabilities. Let's take a look at an example. In the global scope, variables and functions are attached to the global object (window in browsers):
/* Global scope */
var globalVariable = 'Hello, world!';
console.log(globalVariable); /* Output: Hello, world! */
In contrast, variables and functions defined in the module scope are not attached to the global object:
The module scope provides a way to encapsulate variables and functions and prevent them from polluting the global namespace.
Considerations:
Global scope (classic scripts): Scripts loaded without type="module" run in the global scope. Any top-level variables or functions they define become properties of the window object.
Module scope (ES modules): Scripts loaded with type="module" use the JavaScript ES module system. Each module has its own scope, so top-level variables and functions do not automatically become global.
Load and execution order: Classic scripts execute in the order they appear. Module scripts are deferred and execute after HTML parsing.
Mixing modules and globals: If you include both, module scripts will not automatically see variables from global scripts unless explicitly referenced.
Using Vite Artifacts in Plain PHP Pages
So, how can we use Vite artifacts in plain PHP pages, while still retaining the ability to run JavaScript in the global scope? The answer lies in using the viteStaticCopy plugin to copy the raw JavaScript file managed by NPM into the folder of our choice with the name of our choice.
Install the static copy plugin using NPM:
npm install vite-plugin-static-copy
Here's a complete working Vite configuration, including the viteStaticCopy plugin in our vite.config.js file:
import {defineConfig} from "vite";
import react from "@vitejs/plugin-react";
import laravel from "laravel-vite-plugin";
import {glob} from "glob";
import basicSsl from "@vitejs/plugin-basic-ssl";
import inject from "@rollup/plugin-inject";
import {viteStaticCopy} from 'vite-plugin-static-copy';
/* Have Vite process all these resources */
let inputs = glob.sync(`resources/css/**/*.css`, {nodir: true});
inputs.push(...glob.sync(`resources/scss/**/*.scss`, {nodir: true}));
inputs.push(...glob.sync(`resources/js/**/*.js`, {nodir: true}));
inputs.push(...glob.sync(`resources/js/**/*.jsx`, {nodir: true}));
inputs.push(...glob.sync(`resources/js/**/*.ts`, {nodir: true}));
inputs.push(...glob.sync(`resources/js/**/*.tsx`, {nodir: true}));
export default defineConfig({
plugins: [
basicSsl(),
inject({
$: "jquery",
jQuery: "jquery",
}),
react(),
laravel({
input: inputs,
refresh: true,
}),
viteStaticCopy({
targets: [
{
src: 'node_modules/jquery/dist/jquery.js',
dest: 'assets/vendor',
rename: 'jquery.js'
}
]
})
],
resolve: {
alias: {
"@": "/resources/js",
},
extensions: [".js", ".ts", ".jsx", ".tsx"],
},
build: {
sourcemap: true,
rollupOptions: {
output: {
entryFileNames: "assets/[name].[hash].js",
chunkFileNames: "assets/[name].[hash].js",
assetFileNames: (assetInfo) => {
/* Preload fonts only if they are woff or woff2 */
if (assetInfo.extname === ".woff2" || assetInfo.extname === ".woff") {
return "fonts/[name].[hash][extname]";
}
return "assets/[name].[hash][extname]";
},
},
},
},
});
The viteStaticCopy(targets) configuration will copy the jQuery library from the node_modules directory into the assets/vendor directory and rename it to jquery.js. Note that you can choose any destination folder and file name you like.
Run npm run build to generate assets.
We can then use this library in our plain PHP pages, while still retaining the ability to run JavaScript in the global scope:
<?php
const BUILD_PATH = '/build/';
$manifest = json_decode(file_get_contents(public_path('build/manifest.json')), true);
$appCss = BUILD_PATH . $manifest['resources/scss/app.scss']['file'];
$appJs = BUILD_PATH . $manifest['resources/js/app.js']['file'];
$jqueryJs = BUILD_PATH . '/assets/vendor/jquery.js' ;
?>
<!-- The processed CSS file can be linked like any other CSS file -->
<link href="<?= $appCss ?>" rel="stylesheet" type="text/css"/>
<!-- The module type is required if you have used any imports in app.js, which will usually be the case -->
<script type="module" src="<?= $appJs ?>"></script>
<!-- With any un-processed JavaScript files, you can use the normal global scope -->
<script type="text/javascript" src="<?= $jqueryJs ?>"></script>
<script type="module">
<!-- This uses the jQuery include in the app.js file processed by Vite -->
$('body').prepend("<h1>Hi!</h1>");
</script>
<script type="text/javascript">
<!-- This uses the jQuery from the the raw jquery.js file loaded into the global scope -->
$(function() {
$('body').append("<h1>Bye!</h1>");
});
</script>
In this example, we're using the viteStaticCopy plugin to copy the jQuery library into the assets/vendor directory, and then using it in our plain PHP page, while still using Vite to build and manage our CSS and JavaScript artifacts.
Conclusion
In conclusion, using Vite artifacts in plain PHP pages can be a challenge, especially when it comes to managing CSS and JavaScript artifacts between old and new code. However, by leveraging the advantages of using NPM to manage JavaScript versions and Vite to process CSS and JavaScript, we can bridge the gap between these two different approaches.
By understanding the difference between global and module scopes in JavaScript, we can use Vite artifacts in plain PHP pages, while still retaining the ability to run JavaScript in the global scope. The viteStaticCopy plugin provides a way to copy raw JavaScript files managed by NPM into the folder of our choice with the name of our choice, making it easier to use Vite artifacts in plain PHP pages.
I hope this blog post has provided a helpful guide on how to use Vite artifacts in plain PHP pages. By following these steps, you can leverage the advantages of using Vite and NPM to manage your CSS and JavaScript artifacts, while still supporting older code that runs in the global scope.
When you need consistent, repeatable identifiers in your projects,
UUIDv5 can be your go-to solution. Unlike UUIDv4, which is purely random, or other versions that are less random, but still unpredictable,
UUIDv5 combines a namespace with a name (or set of attributes) to produce the same UUID
for the same input pair regardless of the platform or programming language. This is highly useful when you have data that should map to a
fixed identifier—like a country code or an organizational unit—where you always want to
get back the exact same UUID for that data.
Introduce the four standard UUIDv5 namespaces: DNS, URL, OID, and X.500.
Show simple examples using DNS, URL, and OID, including their full names and brief definitions.
Dive deeper into the X.500 namespace.
Discuss how to create UUIDv5-based database keys from existing uniqueness constraints or compound keys using the X.500 namespace.
We’ll use code samples from Symfony’s Symfony\Component\Uid\Uuid component,
but UUIDv5 is available in several libraries across different platforms, which will produce the exact same deterministic UUIDs in all cases.
Quick Examples: DNS, URL, and OID Namespaces
Before diving into X.500, here are three simple examples demonstrating how to generate deterministic
UUIDs using the DNS, URL, and OID namespaces.
1. DNS Example
DNS stands for Domain Name System, a hierarchical naming system used
to resolve domain names into IP addresses.
A DNS name typically looks like threeleaf.com or subdomain.example.org.
use Symfony\Component\Uid\Uuid;
/**
* Generate a deterministic UUID using the DNS namespace.
*
* @param string $hostname The hostname to convert.
* @return string The deterministic UUID for the given hostname.
*/
function generateDnsUuid(string $hostname): string
{
/* Generate a deterministic UUIDv5: */
$dnsUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_DNS),
$hostname
);
return (string) $dnsUuid;
}
/* Example usage: */
$hostname = 'threeleaf.com';
echo generateDnsUuid($hostname);
2. URL Example
URL stands for Uniform Resource Locator, a reference (an address)
to a resource on the internet.
A URL typically looks like https://threeleaf.com/blog.
/**
* Generate a deterministic UUID using the URL namespace.
*
* @param string $url The URL to convert.
* @return string The deterministic UUID for the given URL.
*/
function generateUrlUuid(string $url): string
{
/* Generate a deterministic UUIDv5: */
$urlUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_URL),
$url
);
return (string) $urlUuid;
}
/* Example usage: */
$url = 'https://threeleaf.com/blog';
echo generateUrlUuid($url);
3. OID Example
OID stands for Object Identifier, a globally unique identifier used
in various standards (e.g., SNMP, LDAP) to name an object or concept.
An OID typically looks like 1.3.6.1.4.1..., where each number identifies a node in a hierarchy.
/**
* Generate a deterministic UUID using the OID namespace.
*
* @param string $oid The OID string to convert.
* @return string The deterministic UUID for the given OID.
*/
function generateOidUuid(string $oid): string
{
/* Generate a deterministic UUIDv5: */
$oidUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_OID),
$oid
);
return (string) $oidUuid;
}
/* Example usage: */
$oid = '1.3.6.1.4.1';
echo generateOidUuid($oid);
Deep Dive: X.500 Namespaces and Distinguished Names
X.500 is a suite of standards for directory services. It defines a structure
for Distinguished Names (DNs), which act like the “full path” for an entry
in a directory (similar in concept to a file path in a filesystem). Each DN is a concatenation
of attribute-value pairs that uniquely identify an entry. Common attribute keys include:
Because these attributes are hierarchical and fairly stable
(e.g., CN=John A. Marsh), the X.500 namespace is perfectly suited for generating
deterministic UUIDs when referencing directory-like entities.
Generating UUIDs with X.500
To generate a UUIDv5 based on a Distinguished Name, you can use the
NAMESPACE_X500 constant:
/**
* Generate a UUIDv5 based on a Distinguished Name (DN) using the X.500 namespace.
*
* @param string $distinguishedName The distinguished name to convert.
* @return string The deterministic UUID for the given distinguished name.
*/
function generateX500Uuid(string $distinguishedName): string
{
/* Generate a deterministic UUIDv5: */
$uuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$distinguishedName
);
return (string) $uuid;
}
/* Example usage: */
$distinguishedName = 'CN=John A. Marsh';
echo generateX500Uuid($distinguishedName);
$complexDistinguishedName = 'CN=Madison Stutts,OU=Engineering,O=Example Corp,C=US';
echo generateX500Uuid($complexDistinguishedName);
Important note about distinguished name volatility!
Depending on the specific use case, keep in mind that you may want to focus on attributes
that are stable and unique for your application. If you are independently calculating
deterministic UUIDs in several places over a long period of time, you will want to avoid
attributes that might change in that timespan. For example, an application-assigned user
ID or government-assigned ID might be considered permanent, whereas a user’s personal email
address or phone number might change.
Creating UUID Database Keys
In many applications, you already have unique identifiers—like an internal employee ID or
a composite key based on a combination of columns. By converting these existing keys into
UUIDv5 values (using NAMESPACE_X500 in this case), you ensure you still get
deterministic UUIDs while leveraging your current uniqueness constraints.
1. Converting a Non-UUID Employee ID into a UUID
Suppose you have a table employee with a unique, non-UUID primary key
employee_id, such as 'EMP12345'. Since
employeeNumber is a standard X.500 attribute for an employee’s
unique ID, you could do:
/**
* Convert a non-UUID employee ID into a UUID.
*
* @param string $employeeId The employee ID to convert.
* @return string The deterministic UUID for the given employee ID.
*/
function generateEmployeeUuid(string $employeeId): string
{
/* Construct an X.500 "distinguished name" style string: */
$distinguishedName = 'employeeNumber=' . $employeeId;
/* Generate a deterministic UUIDv5: */
$employeeUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$distinguishedName
);
return (string) $employeeUuid;
}
/* Example usage: */
$employeeId = 'EMP12345';
echo generateEmployeeUuid($employeeId);
Here, every time you use "employeeNumber=EMP12345" with
NAMESPACE_X500, you’ll get the same UUID, which can be stored or used in
foreign keys.
2. Generating UUIDs from a Compound Key (Phone + Email)
Sometimes, uniqueness is enforced by a combination of columns—for example,
phone_number and email. Two relevant LDAP attributes here are
telephoneNumber and mail:
/**
* Generate a UUID from a compound key (phone + email).
*
* @param string $phoneNumber The customer phone number.
* @param string $email The customer email address.
* @return string The deterministic UUID for the given phone number and email.
*/
function generateCustomerUuid(string $phoneNumber, string $email): string
{
/* Create an X.500-style DN with multiple attributes: */
$compoundDn = 'telephoneNumber=' . $phoneNumber . ',mail=' . $email;
/* Generate the UUID using X.500 namespace: */
$userUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$compoundDn
);
return (string) $userUuid;
}
/* Example usage: */
$phoneNumber = '+1234567890';
$email = 'john.marsh@example.com';
echo generateCustomerUuid($phoneNumber, $email);
Conclusion
Deterministic UUIDs (UUIDv5) can simplify your data by ensuring the same input
always yields the same output. They’re particularly handy for X.500-style distinguished names,
where hierarchical attributes remain stable over time. By combining a robust namespace like
NAMESPACE_X500 with well-structured DNs, you’ll produce consistent identifiers
throughout your applications.
Whether you’re generating UUIDs for DNS, URL,
OID, or X.500, a Uuid v5 function makes it
straightforward. Just remember to:
Pick the right namespace (DNS, URL, OID, or X.500).
Use suitable and stable attributes when generating UUIDs based on X.500 Distinguished Names.
Leverage UUIDv5 to ensure deterministic results.
Finally, converting existing IDs or compound keys into UUIDv5 can unify how you manage references
throughout your database and company. Once you adopt deterministic UUIDs, you’ll never have to
worry about conflicting keys for the same underlying data.
Happy coding, and enjoy your deterministic UUIDs!
Appendix
Complete PHP Example (uuidv5-test.php)
require __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\Uid\Uuid;
/**
* Generate a deterministic UUID using the DNS namespace.
*
* @param string $hostname The hostname to convert.
*
* @return string The deterministic UUID for the given hostname.
*/
function generateDnsUuid(string $hostname): string
{
/* Generate a deterministic UUIDv5: */
$dnsUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_DNS),
$hostname
);
return (string)$dnsUuid;
}
/**
* Generate a deterministic UUID using the URL namespace.
*
* @param string $url The URL to convert.
*
* @return string The deterministic UUID for the given URL.
*/
function generateUrlUuid(string $url): string
{
/* Generate a deterministic UUIDv5: */
$urlUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_URL),
$url
);
return (string)$urlUuid;
}
/**
* Generate a deterministic UUID using the OID namespace.
*
* @param string $oid The OID string to convert.
*
* @return string The deterministic UUID for the given OID.
*/
function generateOidUuid(string $oid): string
{
/* Generate a deterministic UUIDv5: */
$oidUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_OID),
$oid
);
return (string)$oidUuid;
}
/**
* Generate a UUIDv5 based on a Distinguished Name (DN) using the X.500 namespace.
*
* @param string $distinguishedName The distinguished name to convert.
*
* @return string The deterministic UUID for the given distinguished name.
*/
function generateX500Uuid(string $distinguishedName): string
{
/* Generate a deterministic UUIDv5: */
$uuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$distinguishedName
);
return (string)$uuid;
}
/**
* Convert a non-UUID employee ID into a UUID.
*
* @param string $employeeId The employee ID to convert.
*
* @return string The deterministic UUID for the given employee ID.
*/
function generateEmployeeUuid(string $employeeId): string
{
/* Construct an X.500 "distinguished name" style string: */
$distinguishedName = 'employeeNumber=' . $employeeId;
/* Generate a deterministic UUIDv5: */
$employeeUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$distinguishedName
);
return (string)$employeeUuid;
}
/**
* Generate a UUID from a compound key (phone + email).
*
* @param string $phoneNumber The customer phone number.
* @param string $email The customer email address.
*
* @return string The deterministic UUID for the given phone number and email.
*/
function generateCustomerUuid(string $phoneNumber, string $email): string
{
/* Create an X.500-style DN with multiple attributes: */
$compoundDn = 'telephoneNumber=' . $phoneNumber . ',mail=' . $email;
/* Generate the UUID using X.500 namespace: */
$userUuid = Uuid::v5(
Uuid::fromString(Uuid::NAMESPACE_X500),
$compoundDn
);
return (string)$userUuid;
}
// Example usage section with formatted output:
echo '
Example Usage of UUID Generation Functions
';
echo "
";
// DNS Example
$hostname = 'threeleaf.com';
$dnsResult = generateDnsUuid($hostname);
echo "
import uuid
from typing import Optional
def generate_dns_uuid(hostname: str) -> str:
"""Generate a deterministic UUID using the DNS namespace.
Args:
hostname: The hostname to convert.
Returns:
The deterministic UUID for the given hostname.
"""
return str(uuid.uuid5(uuid.NAMESPACE_DNS, hostname))
def generate_url_uuid(url: str) -> str:
"""Generate a deterministic UUID using the URL namespace.
Args:
url: The URL to convert.
Returns:
The deterministic UUID for the given URL.
"""
return str(uuid.uuid5(uuid.NAMESPACE_URL, url))
def generate_oid_uuid(oid: str) -> str:
"""Generate a deterministic UUID using the OID namespace.
Args:
oid: The OID string to convert.
Returns:
The deterministic UUID for the given OID.
"""
return str(uuid.uuid5(uuid.NAMESPACE_OID, oid))
def generate_x500_uuid(distinguished_name: str) -> str:
"""Generate a UUIDv5 based on a Distinguished Name (DN) using the X.500 namespace.
Args:
distinguished_name: The distinguished name to convert.
Returns:
The deterministic UUID for the given distinguished name.
"""
return str(uuid.uuid5(uuid.NAMESPACE_X500, distinguished_name))
def generate_employee_uuid(employee_id: str) -> str:
"""Convert a non-UUID employee ID into a UUID.
Args:
employee_id: The employee ID to convert.
Returns:
The deterministic UUID for the given employee ID.
"""
distinguished_name = f'employeeNumber={employee_id}'
return str(uuid.uuid5(uuid.NAMESPACE_X500, distinguished_name))
def generate_customer_uuid(phone_number: str, email: str) -> str:
"""Generate a UUID from a compound key (phone + email).
Args:
phone_number: The customer phone number.
email: The customer email address.
Returns:
The deterministic UUID for the given phone number and email.
"""
compound_dn = f'telephoneNumber={phone_number},mail={email}'
return str(uuid.uuid5(uuid.NAMESPACE_X500, compound_dn))
def print_example_header():
print("
This blog post demonstrates how to create a simple single-page CRUD (Create, Read, Update, Delete) API using only core PHP. The purpose of this project is to provide a clear and straightforward example for beginners who want to understand how to develop a RESTful API in PHP without using frameworks.
System Requirements
To run this project, ensure you have the following installed:
PHP: This example uses the latest PHP features and syntax available in version 8.2.
MariaDB: The example requires a MariaDB or MySQL instance for the database operations.
cURL: A command-line tool for sending HTTP requests. Note that any REST client can be used to test the API endpoints.
Composer: The composer.json file is included to provide context for PHP server requirements and dependencies, but it is optional for running this project.
Setup Instructions
Create the api.php file: Place the api.php file on any machine that has PHP configured.
Configure Database Connection: Ensure the database connection settings in the api.php file are correctly set for your database instance. This will allow the API to connect to the database and perform necessary operations.
Run the PHP Server: Start the PHP built-in server in the same folder as api.php to use the example REST calls as-is:
php -S localhost:8080
The Code
<?php
/*
* CRUD API Example in core PHP.
*
* This script provides a basic implementation of a CRUD (Create, Read, Update, Delete) API
* using PHP, PDO for database interactions, and JSON for data exchange. The API supports
* creating, reading, updating, and deleting customer records in a MySQL database.
* It also includes endpoints for setting up and tearing down the customers table, which are
* available for illustrative purposes and convenience in this example, but should never be
* placed in a production environment.
*/
$host = '127.0.0.1';
$dbname = 'testing';
$username = 'username';
$password = 'password';
try {
/* Establish database connection */
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $exception) {
die('Database connection failed: ' . $exception->getMessage());
}
/**
* Validate user input data for creating or updating a customer.
*
* @param string[] $data The data to validate
*
* @return string[] The array of validation errors
*/
function validateInput(array $data): array
{
$errors = [];
if (empty($data['firstName'])) {
$errors[] = 'First name is required';
}
if (empty($data['lastName'])) {
$errors[] = 'Last name is required';
}
if (empty($data['email']) || !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Valid email is required';
}
return $errors;
}
/* Retrieve HTTP method and path segments */
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', trim($path, '/'));
/* Determine the resource and customer ID (if any) from the URL */
$resource = $segments[1] ?? '';
$customerId = $segments[2] ?? '';
switch ($resource) {
case 'up':
if ($method === 'POST') {
try {
/* Create 'customers' table if it doesn't exist */
$sql = 'CREATE TABLE IF NOT EXISTS customers (
customerId CHAR(36) DEFAULT uuid() PRIMARY KEY,
firstName VARCHAR(255) NOT NULL,
lastName VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)';
$pdo->exec($sql);
echo json_encode(['message' => 'Table created successfully']);
} catch (PDOException $exception) {
http_response_code(500);
echo json_encode(['error' => 'Failed to create table: ' . $exception->getMessage()]);
}
} else {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
break;
case 'down':
if ($method === 'DELETE') {
try {
/* Drop 'customers' table if it exists */
$sql = 'DROP TABLE IF EXISTS customers';
$pdo->exec($sql);
echo json_encode(['message' => 'Table dropped successfully']);
} catch (PDOException $exception) {
http_response_code(500);
echo json_encode(['error' => 'Failed to drop table: ' . $exception->getMessage()]);
}
} else {
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
break;
case 'customers':
switch ($method) {
case 'GET':
if ($customerId) {
/* Read one customer */
$stmt = $pdo->prepare('SELECT * FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
if ($customer) {
echo json_encode($customer);
} else {
http_response_code(404);
echo json_encode(['error' => 'Customer not found']);
}
} else {
/* Read all customers */
$stmt = $pdo->query('SELECT * FROM customers');
$customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($customers);
}
break;
case 'POST':
/* Create a new customer */
$data = json_decode(file_get_contents('php://input'), true);
$errors = validateInput($data);
if (empty($errors)) {
$stmt = $pdo->prepare('INSERT INTO customers (firstName, lastName, email) VALUES (:firstName, :lastName, :email)');
$stmt->execute([
'firstName' => $data['firstName'],
'lastName' => $data['lastName'],
'email' => $data['email']
]);
/* Fetch the customerId of the newly created customer */
$stmt = $pdo->query('SELECT customerId FROM customers ORDER BY created_at DESC LIMIT 1');
$customerId = $stmt->fetchColumn();
echo json_encode(['message' => 'Customer created successfully', 'customerId' => $customerId]);
} else {
http_response_code(400);
echo json_encode(['errors' => $errors]);
}
break;
case 'PUT':
if ($customerId) {
/* Update an existing customer */
$stmt = $pdo->prepare('SELECT COUNT(*) FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
$customerExists = $stmt->fetchColumn();
if ($customerExists) {
$data = json_decode(file_get_contents('php://input'), true);
$errors = validateInput($data);
if (empty($errors)) {
$stmt = $pdo->prepare('UPDATE customers SET firstName = :firstName, lastName = :lastName, email = :email WHERE customerId = :customerId');
$stmt->execute([
'firstName' => $data['firstName'],
'lastName' => $data['lastName'],
'email' => $data['email'],
'customerId' => $customerId
]);
echo json_encode(['message' => 'Customer updated successfully']);
} else {
http_response_code(400);
echo json_encode(['errors' => $errors]);
}
} else {
http_response_code(404);
echo json_encode(['error' => 'Customer not found']);
}
} else {
http_response_code(400);
echo json_encode(['error' => 'Customer ID is required']);
}
break;
case 'DELETE':
if ($customerId) {
/* Delete an existing customer */
$stmt = $pdo->prepare('DELETE FROM customers WHERE customerId = :customerId');
$stmt->execute(['customerId' => $customerId]);
echo json_encode(['message' => 'Customer deleted successfully']);
} else {
http_response_code(400);
echo json_encode(['error' => 'Customer ID is required']);
}
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
break;
}
break;
default:
http_response_code(404);
echo json_encode(['error' => 'Endpoint not found']);
break;
}
Operation Sequence Diagram
Below is a sequence diagram that shows the flow of API requests and interactions with the database.
API Endpoints
This API provides the following endpoints:
1. Bring the Application Up
URL:/api.php/up
Method:POST
Description: Initializes the application and creates the customers table in the database.
curl --request POST \
--url http://localhost:8080/api.php/up \
--header 'Content-Type: application/json'
This example demonstrates a fundamental RESTful API using core PHP and MariaDB. It is an excellent starting point for beginners looking to understand the basics of API development without requiring a framework. You can use this code to build upon and expand your knowledge of RESTful services in PHP.
In the world of PHP development, strings are everywhere—from building dynamic HTML content to handling user input and managing database queries. But how you piece those strings together can significantly impact the performance, readability, and security of your code. While concatenating strings might seem like a basic task, choosing the right method can be the difference between efficient, maintainable code and a sluggish, hard-to-read mess. Let’s dive into the various ways to concatenate strings in PHP, explore their implications, and help you make informed decisions in your coding adventures.
1. Concatenation Operator (.)
The dot (.) operator is the workhorse of PHP string concatenation. It’s simple, intuitive, and widely used.
$str = "Hello" . " " . "World!";
Good Implications:
Simplicity: The . operator is straightforward and easy to use.
Ubiquity: It’s the most common method of concatenation in PHP, so it’s easily understood by most developers.
Bad Implications:
Performance: In loops or when concatenating many strings, using . can lead to performance issues as PHP repeatedly allocates memory for the new strings.
Readability: Concatenating multiple strings with . can reduce code readability, especially with complex expressions.
2. Concatenation Assignment Operator (.=)
When you want to append a string to an existing variable, the .= operator is your friend.
$str = "Hello";
$str .= " World!";
Good Implications:
Efficiency:.=, which modifies the original string in place, is more efficient than repeatedly using ..
Cleaner Code: It reduces the need for multiple variable assignments, making the code more compact.
Bad Implications:
Performance Overhead: While more efficient than ., it can still cause performance degradation in large loops or heavy string operations.
3. Double-Quoted Strings with Variable Interpolation
PHP’s double-quoted strings allow you to insert variables directly into the string, making it a popular choice for combining strings and variables.
$name = "John";
$str = "Hello, $name!";
Good Implications:
Readability: Variable interpolation makes your code cleaner and easier to read, especially when combining multiple variables and strings.
Simplicity: Eliminates the need for explicit concatenation.
Bad Implications:
Complexity in Expressions: Interpolating complex expressions can lead to confusion and potential syntax errors.
Security Risks: Direct interpolation of user input can introduce security vulnerabilities if not properly sanitized.
Limitations with "Deep" Variables: When dealing with "deep" variables (e.g., $parentClass->childClass->variable), simple interpolation can fail or produce unexpected results. In these cases, you should break down the expression or use concatenation with the . operator for clarity.
Example of a Deep Variable Issue:
echo "Variable: $parentClass->childClass->variable"; // This may not work as expected
Efficiency:implode() is ideal for joining large numbers of strings, especially when they are already stored in an array.
Cleaner Code: It provides a more organized way to handle multiple strings compared to repeated concatenation.
Bad Implications:
Overkill: For simple or one-off string concatenations, using implode() might be more complex than necessary.
Array Requirement: You need to have your strings in an array, which might not always be practical.
Conclusion
String concatenation in PHP offers multiple methods, each with its own strengths and weaknesses. Whether you’re looking for simplicity, performance, readability, or flexibility, there’s a method that fits your needs. However, understanding the implications of each approach is crucial for writing clean, efficient, and maintainable code. The next time you find yourself piecing strings together in PHP, consider the best tool for the job—and remember that sometimes, the simplest approach is the best one. And if you’re dealing with "deep" variables in classes, keep in mind the limitations of simple interpolation and adjust your approach accordingly. Happy coding!
HTTP requests are inherently stateless, meaning each request from a client to a server is independent, with no inherent connection to previous requests. This stateless nature poses challenges when maintaining continuity and user-specific data across multiple interactions with a web application. PHP addresses this issue through session management, as depicted in the diagram. By using sessions, PHP allows for the storage of user-specific data on the server, while a session ID stored in the client’s browser cookie ties individual requests together. This approach enables PHP to maintain state across multiple requests, allowing for a consistent user experience despite the stateless nature of HTTP. The diagram illustrates how PHP handles session creation, continuity, and expiration, ensuring that user data persists across different interactions with the application.
When working with Laravel Eloquent Models, setting default values for various attributes can be an essential requirement. In this post, we'll explore five different ways to set default values in a Laravel 10 Eloquent Model, each with unique characteristics and use cases.
Use of the $attributes Array
The simplest and most straightforward way to set default values for your Eloquent model's attributes. Only accepts scalar defaults and applies only to the initial object.
Using Accessors
Allows considering other attributes of the Model and applies dynamically throughout the lifecycle of the Model. It enables manipulation of attribute values dynamically.
Using Database Defaults
Best for attributes that have little to do with data retrieved by the application, like timestamps and IDs. It may also be used as a last resort in some cases.
Use of Protected static function boot()
Allows using a method or service to set a default value at initialization. Useful when scalar defaults are not sufficient.
Using CastsAttributes
Casting allows converting attribute values and setting defaults through custom casting. Requires that the attribute already be set when retrieving and may require setting an initial value (typically null) in the $attributes array.
Example: Product Model
Let's create a Product model that utilizes all the mentioned techniques on different fields:
use Illuminate\Database\Eloquent\CastsAttributes;
class Product extends Model
{
protected $attributes = [
'status' => 'active',
'metadata' => null, // Initial value for custom cast
];
protected $casts = [
'metadata' => MetadataCast::class, // Custom cast for metadata
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->slug = Str::slug($model->name);
});
}
public function getPriceAttribute($value)
{
// Apply a discount or format the price based on other attributes
return $value * 0.9; // Example: 10% discount
}
public function getStatusAttribute($value)
{
return $value ?: 'active';
}
}
class MetadataCast implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return json_decode($value) ?: ['default_key' => 'default_value'];
}
public function set($model, $key, $value, $attributes)
{
return json_encode($value);
}
}
// Migration example for database defaults
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug');
$table->decimal('price');
$table->string('status')->default('active');
$table->timestamps(); // created_at will be set by default
});
In this example, different attributes of a product are handled using different techniques, demonstrating the flexibility and power of Laravel's Eloquent.
Conclusion
Setting default values in Laravel Eloquent Models can be achieved in various ways, each with its own strengths and use cases. From the simplest $attributes array to more complex boot methods and custom casting, Laravel provides a rich set of tools for managing default values. The provided example illustrates how these can be combined in a cohesive manner to create a robust and flexible model.
I hope this has been helpful in understanding the different techniques available. If you have any questions or need further clarification on any of the methods discussed, please feel free to leave a comment below. Additionally, if you have discovered or utilized other ways to set default values in Laravel that were not covered in this post, we encourage you to share them with the community. Your insights and contributions can help others in their development journey.
In the process of migrating a proprietary PHP application to the Laravel 10 framework, I faced an interesting challenge. The application I was working on had 44 service classes. In Laravel, service classes are typically registered manually in the AppServiceProvider.php file. However, the thought of manually registering all these services seemed daunting and inefficient. Plus, it would be a hassle to update the AppServiceProvider.php every time a service is added, renamed, or removed. Therefore, I decided to find a way to register these service classes dynamically. This post outlines the solution I came up with.
Problem Statement
When migrating a large PHP application into Laravel, manually registering a large number of service classes is not only tedious but also prone to errors. Moreover, it's not scalable: every time we add, rename, or remove a service, we need to manually update the AppServiceProvider.php file. We need a solution that allows us to dynamically register all service classes in the application and automatically adjust when changes are made.
Solution
The solution I came up with involves using Laravel's File::allFiles() method to get all PHP files in the service classes directory and then dynamically register these classes in the AppServiceProvider.php file. The service classes are registered using Laravel's service container, which allows Laravel to automatically resolve these classes when they're needed in other parts of the application.
Here is a code snippet used to find all the classes in any package. I happen to have it in a class called ClassUtil:
/**
* This method is used to recursively retrieve all the classes within a package that have been configured in the Composer autoloader.
*
* @param string $package The package name
*
* @return string[] The classes
*/
public function getPackageClasses(string $package): array
{
/* Get all PHP files in the package directory */
try {
$basePath = base_path($package);
$files = File::allFiles($basePath);
} catch (Exception) {
/* Catches the case where the default Laravel "App" package resides in the "app" folder and the server is case-sensitive. */
$basePath = base_path(lcfirst($package));
$files = File::allFiles($basePath);
}
error_log($basePath);
$rootPath = str_replace(str_replace('/', DIRECTORY_SEPARATOR, $package), '', $basePath);
$classes = [];
foreach ($files as $file) {
/* Convert the file path to a namespaced class name */
$class = str_replace(
['/', '.php'],
['\\', ''],
Str::after($file->getRealPath(), $rootPath)
);
/* Check if the class exists and is not abstract */
if (class_exists($class) && !(new ReflectionClass($class))->isAbstract()) {
$classes[] = $class;
}
}
return $classes;
}
And this is how I use it in AppServiceProvider.php:
/**
* Register any application services.
*
* @return void
*/
public function register(): void
{
parent::register();
foreach ((new ClassUtil())->getPackageClasses('App/Services') as $class) {
$this->app->singleton($class, function () use ($class) {
return new $class();
});
}
}
Benefits
This technique has several benefits:
Simplicity: It saves us the trouble of manually registering each service class.
Scalability: It allows us to easily add, rename, or remove services without having to manually update the AppServiceProvider.php file.
Flexibility: It provides a flexible way of managing service classes, especially in large applications.
Conclusion
Dynamically registering service classes in Laravel is a handy trick that can save you a lot of time and effort, especially when dealing with large applications. I hope this post helps you in your Laravel development journey. If you have any questions or comments, feel free to leave them below!
When working with XML data in PHP, the SimpleXMLElement class provides a convenient way to create and manipulate XML structures. One common requirement is to create a SimpleXMLElement and add it as a child to another SimpleXMLElement. In this blog post, we'll explore the correct solution to achieve this.
Creating the Parent and Child Elements
/* Create the parent SimpleXMLElement */
$parent = new SimpleXMLElement('<parent></parent>');
/* Create the child SimpleXMLElement */
$child = new SimpleXMLElement('<child></child>');
Now comes the crucial part: importing and nesting the child element within the parent element. We'll use the dom_import_simplexml() function to convert the SimpleXMLElement objects to DOMNode objects. Here's how it's done:
In the above code, we import the child element into the parent element's document using the importNode() method. The second argument true indicates that we want to import the entire subtree of the child node.
Printing the Final XML Structure
To see the final XML structure, we can call the asXML() method on the parent element:
echo $parent->asXML();
This will output the complete XML structure, including the parent and nested child elements.
The xmlAdopt() Method
To simplify the process of adopting a child element into a parent element, we can use a helper method called xmlAdopt():
/**
* Adopt a SimpleXMLElement into another SimpleXMLElement.
*
* @param SimpleXMLElement $parent the parent element
* @param SimpleXMLElement $child the child element to add to the parent
*/
private function xmlAdopt(SimpleXMLElement $parent, SimpleXMLElement $child): void
{
$domChild = dom_import_simplexml($child);
$domParent = dom_import_simplexml($parent);
$domChild = $domParent->ownerDocument->importNode($domChild, true);
$domParent->appendChild($domChild);
}
Using the xmlAdopt() Method:
$this->xmlAdopt($parent, $child);
Conclusion:
Creating and nesting SimpleXMLElement objects in PHP requires careful handling
Yes, if there is the potential for an undeclared variable to be passed to functions like is_string(), then you must use the isset() function first.
Example:
if(isset($foo) && is_string($foo)) { // Do something with $foo }
The Long Answer
I recently had an error occur in a 3rd party function I use on my web site. The code assumed that at a certain point that a variable would be set and a string function could be run against it. I wanted to modify the if statement to check to see if the variable was a string before continuing with the said block of code. What I did not know was whether or not the is_string function in PHP worked in the same way as the instanceOf operator in Java. In Java, you do not need to detect if the variable is null before the operation, because instanceOf has the built in ability to determine that a null is not an instance of anything.
The reason I wanted to test this is because the error resulted after a customer interaction with the site that I am not able to reproduce (this is intentional, because it involves translating a user's file, which I do not keep a copy of in accordance with my privacy statement).
Example Code
To test this I wrote a PHP page to determines what happens when a variable is in different states. I also expanded the testing to include is_array, is_bool, is_float, is_int, and is_object. I also include some custom error handling, so you can try this at home without filling up your error log.
<?php /* we will do our own error handling */ function jamErrorHandler($errno, $errmsg, $filename, $linenum, $vars) { $errortype = array ( E_ERROR => 'Error', E_WARNING => 'Warning', E_PARSE => 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error', E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error', E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_ALL => 'All Error', E_STRICT => 'Strict Error', E_RECOVERABLE_ERROR => 'Recoverable Error' ); print '<strong>* ' . $errortype[$errno] . ': ' . $errmsg . ' *</strong><br />'; } function jamExceptionHandler($exception){ jamErrorHandler($exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTrace()); } set_error_handler('jamErrorHandler'); set_exception_handler('jamExceptionHandler'); print '<h2>$foo = 123</h2>'; $foo = 123; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = 123.456</h2>'; $foo = 123.456; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = \'123\'</h2>'; $foo = '123'; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = \'abc\'</h2>'; $foo = 'abc'; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = date(\'r\')</h2>'; $foo = date('r'); if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = true</h2>'; $foo = true; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = false</h2>'; $foo = false; if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = array(\'1\', \'a\')</h2>'; $foo = array('1', 'a'); if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>$foo = jamObject()</h2>'; class jamObject { function test() { print 'test'; } } $foo = new jamObject(); if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } if(is_string($foo)) { print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } print '<h2>unset($foo)</h2>'; unset($foo); if(isset($foo)) { print '<strong>$foo is set.</strong><br />'; } else { print '$foo is not set.<br />'; } if(isset($foo) && is_string($foo)) { print '<strong>$foo isset and is a string.</strong><br />'; } else { if(isset($foo)){ print '$foo isset, but is not a string.<br />'; } else { print '$foo is not set, so is not string.<br />'; } } try { if(is_string($foo)) { // Produces error! print '<strong>$foo is a string.</strong><br />'; } else { print '$foo is not a string.<br />'; } } catch (Exception $e) { print '<strong>Error in is_string($foo)</strong>' . $e->getMessage() . '<br />'; } if(is_float($foo)) { print '<strong>$foo is a float.</strong><br />'; } else { print '$foo is not a float.<br />'; } if(is_int($foo)) { print '<strong>$foo is an integer.</strong><br />'; } else { print '$foo is not an integer.<br />'; } if(is_bool($foo)) { print '<strong>$foo is a boolean.</strong><br />'; } else { print '$foo is not a boolean.<br />'; } if(is_object($foo)) { print '<strong>$foo is an object.</strong><br />'; } else { print '$foo is not an object.<br />'; } if(is_array($foo)) { print '<strong>$foo is an array.</strong><br />'; } else { print '$foo is not an array.<br />'; } ?>