tricky: how to check NULL in pdo? - pdo

this code works fine, it gets an image from a DB and writes it into bild.png:
$verbindung = verbinde_mit_db(); # verbindet mit der DB und erledigt die Fehlerbehandlung
$pdostatement = $verbindung-> prepare("select $s from tbbilder WHERE id_bild = $id");
$pdostatement->bindParam(1, $autorenid);
try {
$pdostatement->execute();
}
catch (PDOException $e) {
$meinText .= "<br>PDO Exception <br>select $s from tbbilder WHERE id_bild = $id <br>";
$meinText .= print_r($e, true);
}
$pdostatement->bindColumn(1, $lob, PDO::PARAM_LOB);
file_put_contents('bild.png', $lob); #file_put_contents Schreibt einen String in eine Datei, also hier "$lob" in bild.png
$verbindung = null; # DB Verbindung schließen
return $ok; #### ====> shall be 1 or zero for no image found, how to do it? I tried many ways

finally I found a solution, here it comes:
file_put_contents is not a only a "stand-alone" thing, but is able to return the bytes, it has written. So if there is a $lob, something is written, right?
So you change the lob-saving-line above into:
$size = file_put_contents($filename, $lob);
.......
the trigger, if there is a new file or not is this return: it returns either the file name or an empty thing:
if ($size == 0) { $filename="";}
return $filename;

Related

Perl6: large gzipped files read line by line

I'm trying to read a gz file line by line in Perl6, however, I'm getting blocked:
How to read gz file line by line in Perl6 however, this method, reading everything into :out uses far too much RAM to be usable except on very small files.
I don't understand how to use Perl6's Compress::Zlib to get everything line by line, although I opened an issue on their github https://github.com/retupmoca/P6-Compress-Zlib/issues/17
I'm trying Perl5's Compress::Zlib to translate this code, which works perfectly in Perl5:
use Compress::Zlib;
my $file = "data.txt.gz";
my $gz = gzopen($file, "rb") or die "Error reading $file: $gzerrno";
while ($gz->gzreadline($_) > 0) {
# Process the line read in $_
}
die "Error reading $file: $gzerrno" if $gzerrno != Z_STREAM_END ;
$gz->gzclose() ;
to something like this using Inline::Perl5 in Perl6:
use Compress::Zlib:from<Perl5>;
my $file = 'chrMT.1.vcf.gz';
my $gz = Compress::Zlib::new(gzopen($file, 'r');
while ($gz.gzreadline($_) > 0) {
print $_;
}
$gz.gzclose();
but I can't see how to translate this :(
I'm confused by Lib::Archive example https://github.com/frithnanth/perl6-Archive-Libarchive/blob/master/examples/readfile.p6 I don't see how I can get something like item 3 here
There should be something like
for $file.IO.lines(gz) -> $line { or something like that in Perl6, if it exists, I can't find it.
How can I read a large file line by line without reading everything into RAM in Perl6?
Update Now tested, which revealed an error, now fixed.
Solution #2
use Compress::Zlib;
my $file = "data.txt.gz" ;
my $handle = try open $file or die "Error reading $file: $!" ;
my $zwrap = zwrap($handle, :gzip) ;
for $zwrap.lines {
.print
}
CATCH { default { die "Error reading $file: $_" } }
$handle.close ;
I've tested this with a small gzipped text file.
I don't know much about gzip etc. but figured this out based on:
Knowing P6;
Reading Compress::Zlib's README and choosing the zwrap routine;
Looking at the module's source code, in particular the signature of the zwrap routine our sub zwrap ($thing, :$zlib, :$deflate, :$gzip);
And trial and error, mainly to guess that I needed to pass the :gzip adverb.
Please comment on whether my code works for you. I'm guessing the main thing is whether it's fast enough for the large files you have.
A failed attempt at solution #5
With solution #2 working I would have expected to be able to write just:
use Compress::Zlib ;
.print for "data.txt.gz".&zwrap(:gzip).lines ;
But that fails with:
No such method 'eof' for invocant of type 'IO::Path'
This is presumably because this module was written before the reorganization of the IO classes.
That led me to #MattOates' IO::Handle like object with .lines ? issue. I note no response and I saw no related repo at https://github.com/MattOates?tab=repositories.
I am focusing on the Inline::Perl5 solution that you tried.
For the call to $gz.gzreadline($_): it seems like gzreadline tries to return the line read from the zip file by modifying its input argument $_ (treated as an output argument, but it is not a true Perl 5 reference variable[1]), but the modified value is not returned to the Perl 6 script.
Here is a possoble workaround:
Create a wrapper module in the curent directory, e.g. ./MyZlibWrapper.pm:
package MyZlibWrapper;
use strict;
use warnings;
use Compress::Zlib ();
use Exporter qw(import);
our #EXPORT = qw(gzopen);
our $VERSION = 0.01;
sub gzopen {
my ( $fn, $mode ) = #_;
my $gz = Compress::Zlib::gzopen( $fn, $mode );
my $self = {gz => $gz};
return bless $self, __PACKAGE__;
}
sub gzreadline {
my ( $self ) = #_;
my $line = "";
my $res = $self->{gz}->gzreadline($line);
return [$res, $line];
}
sub gzclose {
my ( $self ) = #_;
$self->{gz}->gzclose();
}
1;
Then use Inline::Perl5 on this wrapper module instead of Compress::Zlib. For example ./p.p6:
use v6;
use lib:from<Perl5> '.';
use MyZlibWrapper:from<Perl5>;
my $file = 'data.txt.gz';
my $mode = 'rb';
my $gz = gzopen($file, $mode);
loop {
my ($res, $line) = $gz.gzreadline();
last if $res == 0;
print $line;
}
$gz.gzclose();
[1]
In Perl 5 you can modify an input argument that is not a reference, and the change will be reflected in the caller. This is done by modifying entries in the special #_ array variable. For example: sub quote { $_[0] = "'$_[0]'" } $str = "Hello"; quote($str) will quote $str even if $str is not passed by reference.

PHP InstanceOf works locally but not on host server

I have an issue with PHP 7's instanceof statement that is only happening on certain conditions.
It seems that instanceof works locally on my dev machine (MAMP Pro running PHP 7.0.13) but not on my Hosted Server (HostEurope, PHP 7).
I have tried the following :
downgrading to PHP 5.6
using is_a instead
Using fully qualified name e.g. \Site\Ad
but they all exhibit the same behaviour.
I've tried Googling "PHP instanceof not working" and variations of it but I haven't found anything relevant.
I was wondering if anyone had experienced something similar or possible solutions to try?
The Code in question is:
<?php
namespace Site;
require_once(__DIR__."/../interface/IOutput.php");
require_once(__DIR__."/../lib/Lib.php");
require_once(__DIR__."/../site/AdMediumRectangle.php");
require_once(__DIR__."/../site/AdSnapBanner.php");
require_once(__DIR__."/../const/Const.php");
class AdFactory
{
/**
* Define(AD_BANNER, 0);
* Define(AD_RECTANGE, 1);
* Define(AD_SUPERBANNER, 2);
* Define(AD_SKYSCRAPER, 3);
**/
/**
* #param $object
* #return AdMediumRectangle|AdSnapBanner|string
*/
public static function CreateObject($object)
{
$ad = wire(pages)->get("/ads/")->children->getRandom();
if ($ad == null)
return new \Exception("No Random Ad found");
switch ($object) {
case AD_BANNER:
echo "AD_Banner Selected\r\n";
$adSnapBanner = new AdSnapBanner($ad);
return $adSnapBanner;
break;
case AD_RECTANGLE:
echo "AD Rectangle Created\r\n";
$adRectangle = new AdMediumRectangle($ad);
return $adRectangle;
break;
case AD_SUPERBANNER:
case AD_SKYSCRAPER:
default:
echo "AdFactory BlankObject created";
return "";
break;
}
}
public static function Markup($object)
{
$obj = AdFactory::CreateObject($object);
if (($obj instanceof AdSnapBanner) || ($obj instanceof AdMediumRectangle)) {
echo "InstanceOf worked";
return $obj->Markup();
}
else {
echo "return blankString";
return "";
}
}
}
Update : This is the code that calls the above AdFactory class
<?php
namespace Site;
require_once(__DIR__."/../interface/IOutput.php");
require_once(__DIR__."/../lib/Lib.php");
require_once(__DIR__."/../factory/AdFactory.php");
require_once (__DIR__."/../const/Const.php");
class AdInjector
{
public static function Inject($page, $ad_pos)
{
//Select an Ad from /Ads/ according to criteria
//$ads = wire(pages)->get("/ads/")->children;
$count = 1; //$ads->count();
if ($count > 0) {
$mod = $page->id % 3;
echo "mod=" . $mod . "\r\n";
if ($mod == $ad_pos) {
switch ($mod) {
case AD_POS_TITLE;
case AD_POS_BANNER:
//Pick an Snap Banner
echo "Banner Injected (banner):" . AD_BANNER . "\r\n";
return AdFactory::Markup(AD_BANNER);
break;
case AD_POS_SIBLINGS:
echo "Banner Injected (rect):" . AD_RECTANGLE . "\r\n";
//Pick an Ad Rectangle
return AdFactory::Markup(AD_RECTANGLE);
break;
default:
return "";
break;
}
} else
return "";
} else
return "";
}
}
instanceof is a language construct which is so essential to PHP that it is de facto impossible not to work properly.
The code you provided is not enough to tell where the issue might be happening.
Chances are, you have a folder not readable on your online server and simply get somewhere a null value instead of an expected object along your code. Ask yourself: "If it is not the object I expect, what else is it?"
Use var_dump() or printf() to investigate what your variables actually contain and you will find the error soon.
For your code, PHPUnit tests would be a benefit, or at least the use of assert() here and there in your code.
Turns out there was a bug in 1 of the API calls I was making to the Processwire CMS.
$ad = wire(pages)->get("/ads/")->children->getRandom();
And my local and server instance of Processwire was not the same version, which was news to me. I normally have it synchronised, including any modules I use.
I also suspect my null check is not correct PHP, to add to the problem.
It has to do with namespaces used in the code:
Locally (Code with no namespaces) I used this, working fine:
if ($xmlornot instanceof SimpleXMLElement) { }
But on the server (code with namespaces) only this worked:
if ($xmlornot instanceof \SimpleXMLElement) { }
See also this question/answer: instanceof operator returns false for true condition

Losing time with displays and printed content when cleaning XML files

I'm trying to create a PowerShell routine to clean XML files automatically. I have succesfully created my routine, and I'm able to clear a file with different functions and scripts. But I want to launch my PowerShell routine every time that I have new XML file. So I've decided to add a system to deal with every files in a directory.
Now that I'm calling my routine to clean my PowerShell scripts, even if I don't use Write-Host, It displays rows when I'm launching my routine, and I'm losing a lot of time to clear XML files.
Here is my code:
param ([string] $sourceDirectory, [string] $targetDirectory, [string] $XSDFileName, [string] $dataSourceName, [string] $databaseName)
clear
function clearLocalVariables{
#This functions clears my local variables
}
function createSQLNodesList{
param ([string] $dataSourceName,[string] $databaseName)
#This function creates a list of available and allowed nodes in my XML Files from SQL databases.
}
The following functions are used to check my nodes, and this is where the prints and Write-Host appears when it's launched more than once:
function isNodeNameValid {
param ([string] $testedNodeName)
# This function is used to return the value of the nodeAnalysis function.
# It selects wich list the node will be analysed depending on the fact that
# it is a node for the aspect of the XML or for data.
# - $testedNodeName is a string representing the XML node analysed.
# If the node name is a 5 length string, begins with an A, and is composed of
# 4 digits ('AXXXX'), then it is data.
if(($testedNodeName.Length -eq 5) -and ($testedNodeName.Substring(0,1) -eq "A" ) -and ($testedNodeName.Substring(1,4) -match "^[-]?[0-9.]+$")) {
return nodeAnalysis -nodesList $nodesSQL -testedNodeName $testedNodeName
#Else, it is in the list for the aspect of the XML.
} else {
return nodeAnalysis -nodesList $nodesXML -testedNodeName $testedNodeName
}
}
function nodeAnalysis {
param ($nodesList,[string] $testedNodeName)
# This function is used to analyse each node name given.
# It compares the name of the name analysed to each node in the array given in parameter.
# - $nodesList is the corresponding array depending on the isNodeNameValid() method.
# - $testedNodeName is a string representing the XML node analysed.
# We compare each node of the node array to the testedNodeName. If the testedNodeName is in this array, the method returns 1.
foreach($nodeName in $nodesList) {
if ($testedNodeName -eq $nodeName) {
return 1
}
}
#If the node correspond to any node of the list, then the method returns 0.
return 0
}
# -- XML Nodes recursive cleaning method -- #
function cleanXMLContent {
param ($XMLDoc,[int] $endOfLeaf, [int] $boucle)
#This is the function I have trouble with displays and efficency :
while($endOfFile -ne 1) {
if($endOfLeaf -eq 1) {
if($XMLDoc.Name -eq "#document"){
$endOfFile = 1
}
if($XMLDoc.NextSibling) {
$XMLDoc = $XMLDoc.NextSibling
$endOfLeaf = 0
} else {
$XMLDoc = $XMLDoc.ParentNode
$endOfLeaf = 1
}
} else {
if(!(isNodeNameValid -testedNodeName $XMLDoc.Name)) {
if($XMLDoc.PreviousSibling) {
$nodeNameToDelete = $XMLDoc.Name
$siblingNodeName = $XMLDoc.PreviousSibling.Name
$XMLDoc = $XMLDoc.ParentNode
$XMLDoc.RemoveChild($XMLDoc.SelectSingleNode($nodeNameToDelete))
$XMLDoc = $XMLDoc.SelectSingleNode($siblingNodeName)
} else {
$nodeNameToDelete = $XMLDoc.Name
$XMLDoc = $XMLDoc.ParentNode
$XMLDoc.RemoveChild($XMLDoc.SelectSingleNode($nodeNameToDelete))
}
} else {
if($XMLDoc.HasChildNodes) {
$XMLDoc = $XMLDoc.FirstChild
$endOfLeaf = 0
} else {
if($XMLDoc.NextSibling) {
$XMLDoc = $XMLDoc.NextSibling
$endOfLeaf = 0
} else {
if($XMLDoc.ParentNode) {
$XMLDoc = $XMLDoc.ParentNode
if($XMLDoc.NextSibling) {
$endOfLeaf = 1
} else {
$XMLDoc = $XMLDoc.ParentNode
$endOfLeaf = 1
}
}
}
}
}
}
}
Write-Host "- Cleaning XML Nodes OK" -ForegroundColor Green
}
function createXSDSchema {
param ([string] $XSDFileName)
#This function is used to create XSD corresponding File
}
function cleanFile {
param ([string] $fileName, [string] $source, [string] $target, [string] $XSDFileName, [string] $dataSourceName, [string] $databaseName)
# -- Opening XML File -- #
#Creation of the XML Document iteration path
$date = Get-Date
[string] $stringDate = ($date.Year*10000 + $date.Month*100 + $date.Day) * 1000000 + ($date.Hour * 10000 + $date.Minute* 100 + $date.Second)
$date = $stringDate.substring(0,8) + "_" + $stringDate.substring(8,6)
#determining the path of the source and the target files.
$XMLDocPath = $source + $fileName
$XMLFutureFileNamePreWork = $fileName.Substring(0,$fileName.Length - 4)
$XMLFuturePath = $target + $XMLFutureFileNamePreWork + "cleaned" #_"+$date
#Creation of the XML Document
$XMLDoc = New-Object System.Xml.XmlDocument
$XMLFile = Resolve-Path($XMLDocPath)
#Loading of the XML File
$XMLDoc.Load($XMLFile)
[XML] $XMLDoc = Get-Content -Path $XMLDocPath
#If the XML Document exists, then we clean it.
if($XMLDoc.HasChildNodes) {
#The XML Document is cleaned.
cleanXMLContent $XMLDoc.FirstChild -endOfLeaf 0
Write-Host "- XML Cleaned" -ForegroundColor Green
#If it is a success, then we save it in a new file.
#if($AnalysisFinished -eq 1) {
#Modifying the XSD Attribute
#setting the XSD name into the XML file
createXSDSchema -XSDFileName $XSDFileName
#Creation of the XML Document
$XMLDoc.Save($XMLFuturePath+".xml")
Write-Host "- Creation of the new XML File Successfull at "$XMLFuturePath -ForegroundColor Green
#Creation of the XSD Corresponding Document
#createXSDSchema -XMLPath $XMLFuturePath
#}
} else {
Write-Host "Impossible"
}
}
Here I'm executing the whole process with the different functions. When I'm launching each functions separatly it works, but with many files it displays content and I lose a lot of time:
cd $sourceDirectory
$files = Get-ChildItem $sourceDirectory
# -- Local Variables Cleanning -- #
clearLocalVariables
Write-Host "- Variable cleaning successfull" -ForegroundColor Green
# -- SQL Connection -- #
$nodesSQL = createSQLNodesList -dataSourceName $dataSourceName -databaseName $databaseName
foreach($file in $files){
cleanFile -fileName $file -source $sourceDirectory -target $targetDirectory -XSDFileName $XSDFileName -dataSourceName $dataSourceName -databaseName $databaseName
}
Do you have any idea about how to avoid the different displays of the contents?
I have a lot of blank rows, that multiplies the cleaning time by 10 or 15.
First, refrain from loading XML files twice. Use either
$XMLDoc = New-Object System.Xml.XmlDocument
$XMLDoc.Load($XMLFile)
or
[xml]$XMLDoc = Get-Content -Path $XMLFile
They both do the same thing.
Next, replace the iterative XML traversal with a recursive one:
function Clean-XmlContent {
Param(
[Parameter(Mandatory=$true)]
[Xml.XmlElement]$Node
)
if ($Node.HasChildNodes) {
foreach ($child in $Node.ChildNodes) {
if ($child -is [Xml.XmlElement]) { Clean-XmlContent $child }
}
}
if (-not (Test-NodeName -NodeName $Node.LocalName)) {
$Node.ParentNode.RemoveChild($Node)
}
}
and call it with the XML root node:
Clean-XmlContent $XMLDoc.DocumentElement
Also, simplify the node name validation:
function Test-NodeName {
Param(
[string]$NodeName
)
if ($NodeName -match '^A\d{4}$') {
return ($nodesSQL -contains $NodeName)
} else {
return ($nodesXML -contains $NodeName)
}
}
That should speed up things considerably.
Thanks to Ansgar Wiechers, I have found a way to accelerate my code, I use recursive way to develop my code. This way my code is much faster, but the content of the rows deleted was still printed.
But to avoid having the content of the deleted nodes printed on screen, I had to use :
[void]$RemovedNode.ParentNode.RemoveChild($RemovedNode)
Instead of :
$RemovedNode.ParentNode.RemoveChild($RemovedNode)

i am having a issue with json codeigniter rest its not closing the tag

i am having a problem with json codeigniter rest
i am making this call to the server and the problem its that its not closing the json tags
s, USA","clientUID":"7","email":null,"idipad":"2","dateModified":null},{"id":"19","uid":null,"name":"Wayne Corporation, Inc.","phone":"932345324","address":"Second st. 312, Gotham City","clientUID":"7","email":"waynecorp#gmail.com","idipad":"1","dateModified":null}]
its missing the final }
this is the code that creates the response :
$this->response(array('login'=>'login success!','user_admin_id'=>$user_id,'client'=>$client,'users'=>$users,'projects'=>$projects,'plans'=>$plans,'meetings'=>$meetings,'demands'=>$demands,'tasks'=>$tasks,'presences'=>$presences,'contractors'=>$contractors,'companies'=>$companies), 200);
this is the client call using curl :
$this->curl->create('http://dev.onplans.ch/onplans/index.php/api/example/login/format/json');
// Option & Options
$this->curl->option(CURLOPT_BUFFERSIZE, 10);
$this->curl->options(array(CURLOPT_BUFFERSIZE => 10));
// More human looking options
$this->curl->option('buffersize', 10);
// Login to HTTP user authentication
$this->curl->http_login('admin', '1234');
// Post - If you do not use post, it will just run a GET request
//$post = array('remember'=>'true','email'=>'admin.architect#onplans.ch','password'=>'password');
$post = array('remember'=>'true','email'=>'admin.architect#onplans.ch','password'=>'password');
$this->curl->post($post);
// Cookies - If you do not use post, it will just run a GET request
$vars = array('remember'=>'true','email'=>'manuel#ffff.com','password'=>'password');
$this->curl->set_cookies($vars);
// Proxy - Request the page through a proxy server
// Port is optional, defaults to 80
//$this->curl->proxy('http://example.com', 1080);
//$this->curl->proxy('http://example.com');
// Proxy login
//$this->curl->proxy_login('username', 'password');
// Execute - returns responce
echo $this->curl->execute();
// Debug data ------------------------------------------------
// Errors
$this->curl->error_code; // int
$this->curl->error_string;
print_r('error :::::LOGINN REMOTE:::::'.$this->curl->error_string);
// Information
$this->curl->info; // array
print_r('info :::::::::::::'.$this->curl->info);
the response belong to the rest api codeigniter from phil
/**
* Response
*
* Takes pure data and optionally a status code, then creates the response.
*
* #param array $data
* #param null|int $http_code
*/
public function response($data = array(), $http_code = null)
{
global $CFG;
// If data is empty and not code provide, error and bail
if (empty($data) && $http_code === null)
{
$http_code = 404;
// create the output variable here in the case of $this->response(array());
$output = NULL;
}
// If data is empty but http code provided, keep the output empty
else if (empty($data) && is_numeric($http_code))
{
$output = NULL;
}
// Otherwise (if no data but 200 provided) or some data, carry on camping!
else
{
// Is compression requested?
if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE)
{
if (extension_loaded('zlib'))
{
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
{
ob_start('ob_gzhandler');
}
}
}
is_numeric($http_code) OR $http_code = 200;
// If the format method exists, call and return the output in that format
if (method_exists($this, '_format_'.$this->response->format))
{
// Set the correct format header
header('Content-Type: '.$this->_supported_formats[$this->response->format]);
$output = $this->{'_format_'.$this->response->format}($data);
}
// If the format method exists, call and return the output in that format
elseif (method_exists($this->format, 'to_'.$this->response->format))
{
// Set the correct format header
header('Content-Type: '.$this->_supported_formats[$this->response->format]);
$output = $this->format->factory($data)->{'to_'.$this->response->format}();
}
// Format not supported, output directly
else
{
$output = $data;
}
}
header('HTTP/1.1: ' . $http_code);
header('Status: ' . $http_code);
// If zlib.output_compression is enabled it will compress the output,
// but it will not modify the content-length header to compensate for
// the reduction, causing the browser to hang waiting for more data.
// We'll just skip content-length in those cases.
if ( ! $this->_zlib_oc && ! $CFG->item('compress_output'))
{
header('Content-Length: ' . strlen($output));
}
exit($output);
}
This answer was referenced from Github issue. Also raised by Pedro Dinis, i guest.
I met this problem today and take me long hours to search for the solution. I share here with hope to help someone like me.
The key is to replace around line 430 in the library file: REST_Controller.php :
header('Content-Length: ' . strlen($output));
by
header('Content-Length: ' . strlen("'".$output."'"));
UPDATE: The problem was solved here
Or you can just comment out the code, it will run fine. :)

Help creating selective IF statement

I have this code that sends a text message to your mobile phone...
$text = fopen("../data/textmembers/registry.txt","r") or die("couldent open file");
while (!feof($text)) {
$name = fgets($text);
$number = fgets($text);
$carrier = fgets($text);
$date = fgets($text);
$line = fgets($text);
$content = $_POST['message'];
$message .= $content;
$message .= "\n";
$number = trim($number);
mail($number . "#vtext.com", "SGA Event Alert", $message, "SGA");
Header("Location: mailconf.php");
everything works fine.. Here is my question, if you look at where I have "#vtext.com"
as you may or may not know, each carrier has its own extension, verizon is #vtext.com, at&t is #txt.att.net. I need to take the feed from "$carrier" decide what carrier it is, and then assign the extension to it...
I thought an ifelse would work, but I am not good with if statements...
the user's choices are
Verizon = 1234567890#vtext.com
AT&T = 1234567890#txt.att.net
T-mobile = #tmomail.net
Nextel = #messaging.nextel.com
thanks guys!!
$carriers = array(
"verizon" => "vtext.com",
"at&t" => "txt.att.net",
"t-mobile" => "tmomail.net",
"nextel" => "messaging.nextel.com"
);
Then, you get that value by looking up the key:
print $carriers[strtolower($carrier)];
If $carrier is "Nextel," "messaging.nextel.com" will be returned.
Probably better than using an if statement would be using a switch statement.
Have a look at the section of the PHP manual that deals with the switch statement.