Download arrays, looping, SELECT, songs with features application.

Document related concepts

Microsoft Jet Database Engine wikipedia , lookup

Microsoft SQL Server wikipedia , lookup

Clusterpoint wikipedia , lookup

SQL wikipedia , lookup

Join (SQL) wikipedia , lookup

Database model wikipedia , lookup

Relational model wikipedia , lookup

Transcript
Creating databases for web
applications
Walk before run? Songs with features example.
Retrieve information from database. Recordsets.
Arrays. Loops.
Homework: Get examples working. Post unique source
on entity relationship diagrams or data flow diagrams
OR SQL Select statement.
What does this do?
•
•
•
•
•
•
•
•
<?
$test = $_GET["test"];
$pattern = "/^\\$[0-9]$/i";
if (preg_match($pattern,$test)) {
print("Entry $test passed the test"); }
else {
print("Entry $test failed the test"); }
?>
Money with commas
•
•
•
•
<?
$test = $_GET["test"];
print ("string to be tested is $test");
$pattern = "/^\\$[1-9][0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{2})?$/";
•
•
•
•
•
•
•
•
print ("<br>");
print ("pattern is $pattern");
print ("<br>");
if (preg_match($pattern,$test)) {
print("Entry $test passed the test"); }
else {
print("Entry $test failed the test"); }
?>
Questions?
Any problems
• creating tables in a database
– If a table with that name exists, you need to
DROP TABLE ….. before creating a new one
• INSERT INTO….
• SELECT
Scripts in my books example
• opendbo.php: required by ALL the php files
• createbooktable.php
• addbook.html, which invokes…
• addbook.php
• showbooks.php
• showbooksbycategory1.php, which invokes …
• showbooksbycategory2.php
Note: need to create table and make entries for the
“show” scripts to work.
Questions?
<!DOCTYPE html><html><head><title>List books in a category</title></head><body>
Pick the category you want:
<br/>
<form action="showbooksbycategory2.php" method="get">
Choices: <select name="pickedcategory">
<?php
require("opendbo.php");
$query="SELECT DISTINCT bcategory FROM books";
$categories = mysqli_query($link,$query);
while ($row=mysqli_fetch_array($categories))
{ $cat=$row['bcategory'];
print ("<option value='$cat'>$cat</option><br>\n");
}
mysqli_close($link);
?>
</select>
<input type=submit name=submit value="Choose!"> <br>
</form></body></html>
<!DOCTYPE html><html><head><title>Show books in selected
category</title></head><body>
<?php
$bcat = $_GET['pickedcategory'];
print "Sites in $bcat category <br/>";
require("opendbo.php");
$query="SELECT * FROM books WHERE
bcategory = '$bcat' ORDER BY bdate DESC";
$result=mysqli_query($link,$query);
$NoR=mysqli_num_rows($result);
if ($NoR==0) {
print ("No sites in that category"); }
else { print("<table border='1'>");
print("<tr><th>Title </th><th>Date </th><th>Description
</th></tr>");
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> ".$row['btitle']."</td>");
print ("<td>".$row['bdate']."</td>");
print ("<td>".$row['bdescription']."</td>");
print ("</tr>");
}
print ("</table>");
}
mysqli_close($link);
?>
</body></html>
Database decisions
• Not obvious and can be debated.
• I decided MAINLY to show php features to
NOT have the user enter the date.
• I decided to NOT use ISBN for the primary
key.
• ?
• Part of the course is to get practice making
decisions, so, do something different!
Making connection
• A standard practice is to put the private
information regarding the database in its own
file, say it is called connectcode.php and then
using
require("opendbo.php");
– Or whatever name you choose
in each program that requires connection to the
database.
• My examples used files named
connectcode.php or opendbo.php or something
similar.
– You will need to put in the specifics for your
databases using the information sent to you.
• Some of my examples use $DBname. That is,
the code assumes that has been set with the
database name.
Outline of work
• Understand php and MySQL examples
– Get your own versions working
• Learn [about] system design and documentation
– Find and study sources on ERD and DFD
– Create diagrams for a library
MIDTERM
• Design and build enhanced versions of sample
projects
• Propose, design, present and build your own
projects
Advice
• Showing a lot of php code
• You will need to study it
– use sources
• php scripts are middleware (aka server-side)
– take information from html form or query string and
manipulate it
– often, use to compose SQL queries
– take values returned from queries to compose html
– Composing html and SQL makes use of php tricks
such as variable names inside of quoted strings and
single quotation marks inside of quoted strings
Advice / warning
• Applications involve multiple files, aka
scripts. These scripts are not big!
• Scripts change the environment: the
database, cookies
– That's the whole point!
• So, when there is an error, you may
(often) need to start all over.
– Create tables
– Populate
–…
Songs with features examples
• http://socialsoftware.purchase.edu/jeanine.meyer/example/addsong.
html
– action=addsong.php
• http://socialsoftware.purchase.edu/jeanine.meyer/example/listsongs.
php
• http://socialsoftware.purchase.edu/jeanine.meyer/example/addfeatur
e.html
– action=addfeature.php
• http://socialsoftware.purchase.edu/jeanine.meyer/example/addfeatur
estosong1.php
– action=addfeaturestosong2.php
• http://socialsoftware.purchase.edu/jeanine.meyer/example/findother
s1.php
– action=findothers2.php
• Notice that in some cases, pairs are html and php and in others php
and php.
Song database tables
• songs
• features
• featuresinsongs
Song example scripts
•
•
•
•
•
createtables.php
addsong.html and addsong.php
listsongs.php
addfeature.html and addfeature.php
addfeaturestosong1.php and
addfeaturestosong2.php
• findothers1.php and findothers2.php
• removesong1.php and removesong2.php
<?php
function createtables($tname,$fields) {
global $DBname, $link;
$query = "DROP TABLE $tname";
mysqli_query($link,$query);
$query="CREATE TABLE ".$tname."(".$fields.")";
if (mysqli_query($query)) {
print ("The table, $tname, was created
successfully.<br>\n");
}
else {
print ("The table, $tname, was not created.
<br>\n");
}
}
?>
<html><head><title>Creating movie table </title> </head>
<body>
<?php
require("opendbe.php");
$tname = "songs";
$fields = "sid INT NOT NULL AUTO_INCREMENT
PRIMARY KEY, sname CHAR(50), artist CHAR(50),
sdesc TEXT, syear YEAR";
createtable($tname, $fields);
$tname = "features";
$fields = "fid INT NOT NULL AUTO_INCREMENT
PRIMARY KEY, fname CHAR(30), fdesc TEXT";
createtable($tname, $fields);
$tname = "featuresinsongs";
$fields = "fisid INT NOT NULL AUTO_INCREMENT
PRIMARY KEY, fid INT NOT NULL, sid INT NOT NULL";
createtable($tname, $fields);
mysqli_close($link);
?> </body> </html>
addsong.html
<html> <head> <title>Adding song form</title>
</head>
<body>
<form action="addsong.php">
Song name: <input name="sn"/><br/>
Artist: <input name="sa"/><br/>
Song description:<input name="sd" width="300"/><br/>
Year: <input name="sy"/><br/>
<input type="submit" value="Submit Song"/>
</form>
</body>
</html>
addsong.php
<html> <head><title>Add song to database</title> </head> <body>
<?php
require("opendbe.php");
$tname = "songs";
$sn=addslashes($_GET["sn"]);
$sd=addslashes($_GET["sd"]);
$sa=addslashes($_GET["sa"]);
$sy=$_GET["sy"];
$query = "INSERT INTO $tname values
('0','$sn','$sa','$sd','$sy')";
echo $query;
$result = mysqli_query($link,$query);
if ($result) {
print("The song was successfully added.<br>\n"); }
else {
print ("The song was NOT successfully added. <br>\n"); }
?>
</body> </html>
SELECT
• most important, most common SQL
statement.
• SELECT all or certain fields FROM table
• Soon, we get more complicated and add
conditions.
• Sometimes conditions involves fields in
more than one table.
listsongs.php
<html> <head><title>List songs</title></head> <body>
<?php
require("opendbe.php");
$tname = "songs";
$query="SELECT * FROM $tname";
$result=mysqli_query($link, $query);
print("<table border='1'>");
print("<tr><td>ID</td><td>Name</td><td>Artist</td><td>Description</td><t
d>Year</td></tr>");
while ($row=mysqli_fetch_array($result)) {
print("<tr><td>");
print($row['sid']."</td><td>");
print ($row['sname'] ."</td><td>");
print ($row['artist'] ."</td><td>");
print ($row['sdesc'] ."</td><td>");
print ($row['syear'] ."</td>");
print("</tr>"); }
print ("</table>");
?>
</table></body></html>
Re: features (first ERD)
• Add feature to the features table
• Then add the fact that a specific song has
that feature to the featuresinsongs table.
songs
featuresinsongs
features
sid
fisid
fid
sn
fid
fname
artist
sid
fdesc
sdesc
syear
addfeature.html
<html>
<head>
<title>Adding feature form</title>
</head>
<body>
<form action="addfeature.php">
Feature name: <input name="fn"/><br/>
Feature description:<input name="fd" width="300"/><br/>
<input type="submit" value="Submit Feature"/>
</form>
</body>
</html>
addfeature.php
<html> <head> <title>Add feature to database</title>
</head> <body>
<?php
require("opendbe.php");
$tname = "features";
$fn=$_GET["fn"];
$fd=$_GET["fd"];
$query = "INSERT INTO $tname values ('0','".$fn."',
'".$fd."')";
$result = mysqli_query($link,$query);
if ($result) {
print("The feature was successfully added.<br>\n"); }
else {
print ("The feature was NOT successfully added.
<br>\n"); }
?>
</body> </html>
Comments
• The opendbe.php has database name and
password. It sets $link used later.
• NOTE: trick of php that variable names inside
double quotes get evaluated.
• NOTE: the presence of the single quotes around
strings. These are required by MySQL (and
other DBMS)
• Code needs to be improved: What if name or
description had quotes or slashes?
Try it and then add
$desc =addslashes($desc);
True story
• This happens to me, more than once.
• When copying over an example with song
titles, tried to input
You're the one
• Did not work! Need to 'escape' the
quotation mark (aka apostrophe).
Comments
• [Go over this again next class]
• Put the db connection code in separate
file, to be included in all other files
• The fields are extracted by name.
– Chose not to extract and display mid
• The $rs produced by the SELECT query is
called a recordset. It is like a table. Its
rows can be extracted one at a time.
More SQL
• ALTER: this is for changing or adding a
field definition
– This also can be done in phpmyadmin
• DROP: this is dropping a table. This is
good to do before creating a table, just in
case you already did it OR don't drop it,
and check for errors.
Caution
• My songs with features database may
contain nonsense entries
• Also, no provision for duplicates or near
duplicates…
Another true story
• When I checked the findothers1.php and
findothers2.php, it didn't seem to be
working…
• BECAUSE I had put in only a limited
number of features and no feature was
shared by more than one song!
Remove application
• Need to remove song PLUS all the
feature/song records
• http://socialsoftware.purchase.edu/jeanine.
meyer/example/removesong1.php
from removesong1.php
Select a song to be deleted with its features
<hr/> <form action="removesong2.php">
<table>
<?php
require("opendbe.php");
$query="Select * from songs";
$result=mysqli_query($link, $query);
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> <input type='radio' name='song'
value='".$row['sid']."'/>");
print ($row['sname'] . "</td><td>". $row['artist']
."</td><td>".$row['sdesc']."</td><td>".$row['syear']."</td>
</tr>"); }
?>
</table> <input type="submit" value="PICK SONG TO BE
DELETED"/> </form>
from removesong2.php
<?php
require("opendbe.php");
$sid=$_GET["song"];
$query = "Delete from songs where sid='$sid' limit 1";
print ($query);
$result = mysqli_query($link,$query);
if ($result) {
print("The song $sid was deleted.<br>\n");
}
else {
print ("The song $sid was not deleted. <br>\n");
}
$query = "Delete from featuresinsongs where sid='$sid'";
$result = mysqli_query($link,$query);
if ($result) {
print("The features for song $sid were deleted.<br>\n"); }
else { print ("The features for song $sid were NOT
successfully added. <br>\n"); }
?>
Notes
• The bad results let me know that I had the
name of the tables wrong!
–
–
song for songs
featuresinsong for featuresinsongs
Who are the agents?
• In existing find similar songs applications,
the assigning of features may not be an
end user function…..
• In a general application, for the public,
should have more security.
• Don't let people remove songs….
• MUCH more important, don't let people
create the tables again.
Continue with song example
• Recall 3 tables
– songs
– features
– featuresinsongs
• Previously, showed adding songs and adding
features.
• Now want to provide way to add a feature to a
song DEMONSTRATE
• Select a song and find all songs that share at
least one feature with the selected song
DEMONSTRATE
Notice
• Since the form will make use of check box,
the information passed needs to be an
array.
from addfeaturestosong1.php
<form action="addfeaturestosong2.php"> <table>
<?php
require("opendbe.php");
$query="Select * from songs";
$result=mysqli_query($link, $query);
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> <input type='radio' name='song'
value='".$row['sid']."'/>");
print ($row['sname']
."</td><td>".$row['artist']."</td><td>".$row['sdesc']."</td>
<td>".$row['syear']."</td></tr>");}
?>
</table> <hr/>
<table>
<?php
$query="Select * from features";
$result=mysqli_query($link, $query);
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> <input type='checkbox' name='ft[ ]'
value='".$row['fid']."'/>");
print ($row['fname']
."</td><td>".$row['fdesc']."</td></tr>"); }
?>
</table> <input type="submit" value="Record
features"/> </form>
from addfeaturestosong2.php
<?php
require("opendbe.php");
$tname = "featuresinsongs";
$sid=$_GET["song"];
$ft=$_GET["ft"];
for($i=0; $i < count($ft); $i++) {
$fid=$ft[$i];
$query = "INSERT INTO $tname SET fid='$fid', sid='$sid'";
$result = mysqli_query($link,$query);
if ($result) {
print("The song $sid had feature $fit successfully added.<br>\n");
}
else {
print ("The song $sid had feature $fit NOT successfully added.
<br>\n"); }
}
?>
Your database
• In the ReadMe file on your [regular]
students.purchase.edu account, there was information
for your socialsoftware.purchase.edu (FA2011)
database
– name,
– database name
– password
• In the following example, WKILLORAN is the name,
WKILLORAN_DB is the database name and
PASSWORD is the password.
• The host (held in $host) is a special virtual server set up
for us.
• SUBSTITUTE FROM THE EMAIL SENT TO YOU!
example of a fake connect file
<?php
$host = '127.0.0.1';
$link = mysqli_connect($host, 'WKILLORAN',
'PASSWORD'); if (!$link) {
die('Not connected : ' . mysql_error());
}
if (!mysqli_select_db('WKILLORAN_DB', $link)) {
echo 'Could not select database';
exit; }
$DBname = 'WKILLORAN_DB';
?>
MySQL queries
• ALL return something!
• This can be indication of success or a
pointer to array (like) object holding data
• php has built-in commands for interactions
with MySQL.
• NOTE: also has commands for generic
DBMS
– EXTRA CREDIT opportunity to report on php
and other DBMS or report on comparisons.
Extra credit
Report on
• Ruby on Rails
• Groovy
• ??
SELECT overview
• Extract some or all fields in table(s)
– Also operations: COUNT, SUM, AVG
• Set conditions on which records by expression
involving fields in one or more tables
– WHERE, JOIN … ON
• Aggregate GROUP records
• Set conditions on the aggregated data HAVING
• Set LIMITS
Basic
$query="SELECT * FROM movies";
Could have used
$query ="SELECT mname, mdesc, myear FROM
movies";
– Since I suggested not displaying the mid field
Use $mysqli_fetch_array to extract a row.
This is an associative array that represents the
constructed record of the selected data
The results of $mysqli_fetch_array can be used as a
condition. When it fails, there were no more rows.
Performance
• how much time is taken by an SQL
statement and/or php code
• This can be significant, that is, amount to
something significant in large databases.
• DBMS have tools to determine this and
you also can experiment.
Looping
$query="SELECT * FROM movies";
$rs=mysqli_query( $link,$query);
while ($row=mysqli_fetch_array($rs)){
print($row['mname'] . " (" .$row['myear'] .
"): <br/> ");
print($row['mdesc']);
print("<hr width='500'/>");
}
What looping does
• Builds up a [long] string of html in this case
(string encoded using my own design in
the video clip archive case)
• Use the concatenate operator .
• Note [those pesky] single quotation marks
– For the indexing into the associative array that
is the row of data
– For the attribute values in the html
Caution / Encouragement
• SELECT statements can be equivalent to many
lines of code
So
• Give yourself time to understand and create the
statements.
• You do not have to do it the shortest way and/or
only one statement. This may not even be the
most efficient.
• Build up $query in stages (using .) and
use print ("The query is $query");
Comments
• The AS t and AS v allow you to use a shorter
name in referencing the fields.
• Remember that equality condition in SQL is one
equal sign.
• Remember to use single quotation marks
around strings.
– If $tag is a variable holding a string, the SQL
statement needs the quotation marks!
• The 'sent back' data is itself encoded as a
comma separated list of clip addresses and clip
titles
GROUP HAVING
• SQL can aggregate (GROUP) records
• SQL can accept a condition applied to the
GROUPs
– The WHERE and the JOIN ON apply to the
individual records
• GROUP generally is applied using
aggregate functions, such as
SUM, COUNT, AVG, MIN, MAX
Question
• Assume a table of student information,
including major, gpa, credits
• What are the majors that have the highest
averages among their students AND let's
just consider juniors and seniors?
– Define junior and senior as having more than
60 credits
• This is our operational definition. It can be a
challenge to make these definitions.
– Display the top 3 majors along with their
average GPA
SELECT example
SELECT department, AVG(gpa) FROM student_info
WHERE credits >60
GROUP BY department
HAVING AVG(gpa) > 3
ORDER BY AVG(gpa) DESC
LIMIT 3
Select student records that have more than 60 credits.
Group by common department. Take an average over
the gpa fields. Just select those groups (that is,
departments) where the average is over 3 (over B).
Order from highest to lowest. Just take the first (top) 3.
Select example from songs with
features
• $sid is the id of a selected song
SELECT sname, COUNT(*) as c FROM featuresinsongs
AS f1, songs AS s, featuresinsongs AS f2 WHERE
f1.sid='$sid' AND
f1.fid=f2.fid AND
f2.sid!='$sid' AND
s.sid=f2.sid GROUP BY sname
ORDER BY c DESC, sname
The featuresinsongs table has song id field and feature id
field. The name of a song is in the songs table.
Select all the song and feature records that have features
in common with features possessed by $sid. But don't
select any song/feature row in which the song id IS $sid.
Group by sname. Order from biggest to smallest.
findothers1.php
<form action="findothers2.php"> <table>
<?php
require("opendbe.php");
$query=”SELECT * FROM songs";
$result=mysqli_query($link, $query);
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> <input type='radio' name='song'
value='".$row['sid']."'/>");
print ($row['sname'] ."</td><td>".$row['artist']."</td><td>".
$row['sdesc']."</td><td>".$row['syear']."</td></tr>");
}
?>
</table> <hr/>
<input type="submit" value="Find others"/> </form>
from findothers2.php
<?php
require("opendbe.php");
$tname = "featuresinsongs";
$sid=$_GET["song"];
$query="SELECT sname, COUNT(*) AS c FROM
featuresinsongs AS f1, songs AS s, ";
$query .="featuresinsongs AS f2 WHERE
f1.sid='$sid' ";
$query .="AND f1.fid=f2.fid ";
$query .="AND f2.sid!='$sid' ";
$query .="AND s.sid=f2.sid GROUP BY sname
ORDER BY c DESC, sname";
$result=mysqli_db_query($DBname, $query,
$link);
$nr = mysqli_num_rows($result);
if ($nr<1) {
print ("Sorry, no feature match for that song."); }
else {
print("<table>");
while ($row=mysqli_fetch_array($result)) {
print("<tr>");
print("<td> ".$row['sname']."</td><td>");
print ($row['c'] ."</td></tr>"); } }
?>
</table>
3-tier model
• Database (MySQL data) holds the
information.
• The middleware (php) is the application of
the business decisions.
• The HTML (with JavaScript) program
handles the interactions with people,
including the presentation of results.
• Reflect on this in terms of examples.
Motivation for Diagrams
• Diagrams are tools for the design stage and for
documentation.
• Databases that are more than one table are
represented by Entity Relationship Diagrams.
• Applications (using databases or not) are
represented by Data Flow diagrams.
• Database applications typically involve many
small[er] files/programs/scripts.
• The exact structure of the diagrams less important
than using some type of representation.
• Focus on this next class.
Homework
• Keep practicing with php and MySQL.
• Making additions/enhancements/changes
to the songs project is a possibility for the
next project.
• Find, review, and post reference and
comments on unique source for Entity
Relationship Diagrams and/or Data Flow
Diagrams OR the Select statement in
SQL.