===== CS 328 - Week 10 Lecture 2 - 2025-04-02 ===== ===== TODAY WE WILL ===== * announcements * attempted kinetic activity * quick aside: string concatenation in PHP (end how to get errors to your browser) * aside: variable interpolation in PHP strings * writing your own functions * whirlwind intro to using PHP and OCI to connect to the Oracle student database * prep for next class ===== * should be working on Homework 8! * at-least-1st-attempts due by 11:59 pm on Friday, April 4 * should be reading and working through the activities in zyBooks Chapter 5 - PHP Fundamentals ===== SIDE NOTE: if you are considering taking Humboldt courses in SUMMER 2025 ===== * registration for SUMMER 2025 opens for ***EVERYONE*** on APRIL 14!!!! * from: https://www.humboldt.edu/student-financial-services/summer-term-2025 "For the 2025 Summer term, the university is guaranteeing 4 units, if enrolled in 6 or more units, will be covered for all continuing matriculated undergraduate students. This will cover 4 units of the tuition charge and does not include coverage of mandatory campus-based fees or the additional non-resident tuition if applicable." * see the above link for more information! ===== string concatenation in PHP ===== * you use a . operator instead of + !!!!!!! <-- PHP got that from Perl! <p> <?= "a" . "b" . "c" ?> </p> | | when the PHP is executed, this becomes: v <p> abc </p> * see 328lect10-2.php ===== to turn ON error messages for an individual PHP document on nrs-projects ===== * nrs-projects has PHP error messages turned off by default (that is, in the php.ini file for nrs-projects, there is a setting that keeps PHP error messages from being included in a PHP document's executed results that are sent to the client tier's browser) * (it is not considered good practice to include them in a production setting...) * BUT, they can be very useful in debugging! SO -- happily, nrs-projects IS set up so that individual PHP documents can enable error messages to be included; * near the beginning of your PHP document, (I'd recommend your first regular PHP tag, placed in the head element, and I like to put it after the meta element) <?php ini_set('display_errors', 1); error_reporting(E_ALL); ?> * now, PHP error messages should be enabled BUT NOTE!!!! * certain PHP syntax errors still result in the PHP engine sending no result -- (not unlike how a syntax error can keep a C++ compiler from giving you an executable result...) running your PHP from the nrs-projects command line will sometimes give you a parse-level error message: [nrs-projects]$ php desired_php.php ===== variable interpolation in PHP ===== * WHEN you write a string in double-quotes, if there is a variable name in that string, that variable will be replaced by its value in the computed result ^ | that's varible interpolation * if you don't want variable interpolation, you can write the string in single-quotes, and any $ is just considered a $ (not the start of a variable) <?php $looky = 13; ?> <p> <?= "what is this: $looky" ?> </p> | | when the PHP is executed, this becomes: v <p> what is this: 13 </p> ^^ || <p> <?= 'what is this: $looky' ?> </p> | | when the PHP is executed, this becomes: v <p> what is this: $looky </p> ^^^^^^ |||||| * what if you have a variable and you want to surround its value with NON-whitespace characters? in your double-quotes string, CURLY BRACES immediately before the $ and somewhere after the variable name will make EXPLICIT where the variable name begins and ends <p> <?= "0{$looky}0" ?> </p> | | when the PHP is executed, this becomes: v <p> 0130 </p> ^^ || * see 328lect10-2.php ===== how to write a function in PHP ===== <?php /*=== signature: desired_funct_name: desired_type desired_type --> ret_type purpose: expects description of expected arguments, returns description of return value ===*/ function desired_funct_name( $param1, $param2, ...) { statement; ... statement; return; /* or */ return expr; } * you do not have to have a return statement -- if you do not, the function simply ends when you reach the end of its body * but, like many other languages, if you execute a return statement, the function ends AT that point * see square.php and see how 328lect10-2.php uses: <?php require_once("square.php"); ?> ...in its head element to put square function's definition there, and you can then call the square function as desired in PHP tags within its body ===== using OCI to connect from PHP to Oracle ===== * there are MULTIPLE packages for allowing a PHP engine on an application tier to request actions from the data tier; we want to request actions from an Oracle databases, so we want to use one of the packages for that, and the one supported for the PHP engine on nrs-projects that can talk to the Oracle student database on campus is OCI - Oracle Call Interface ==== * in OCI, you first need to establish a connection between the PHP engine and Oracle oci_connect is a function you can use for this. you call oci_connect with appropriate arguments, it returns a connection object that PHP on the application tier can use to request that SQL statements (and PL/SQL functions and procedures) be run for it on the data tier * (and because the number of connections to the Oracle db on campus is FINITE, class style is to explicitly CLOSE your connection, using: oci_close with your connection object as its argument: oci_close($conn); ...as soon as you are done with the connection!!!!!!!!!!!!!!!! * BUT -- say you have gotten a connection object using oci_connect. BEFORE you close it using oci_close -- what can you DO with the connection? ONE of SEVERAL possibilities: * if the PHP document wants to ask the data tier/Oracle to execute a static query/select statement, it can do so as follows: (static? means it is not dynamic, it is the same hard-coded unchanging query each time -- as opposed to one that gets adapted or built based on user input, for example) * use oci_parse to ask Oracle to set up a query and return a statement object [when I checked https://www.php.net/manual/en/function.oci-parse.php after class, it calls it the statement identifier; hmm!] (not unlike a pre-compilation step, I think???) * use oci_execute to ask Oracle to execute that statement * use oci_fetch to get access to the next row in the result [when I checked https://www.php.net/manual/en/function.oci-fetch.php after class, it says it: "Fetches the next row from [an executed] query into internal buffers accessible..." with a command such as oci_result] * oci_fetch returns true if it succeeded in fetching a next row, and false if there are no more rows to fetch * and, if the oci_fetch succeeded, use oci_result to grab a particular value from that row * (and continue using oci_fetch and oci_result until you have all the rows, or all the rows you want...) * when done with the statement object, free it using oci_free_statement * from https://www.php.net/manual/en/function.oci-free-statement.php: "Frees resources associated with Oracle's cursor or statement" * and when done with the connection object, use oci_close to close the connection! ^^^^ |||| REMEMBER TO DO THIS!!!!!!! * we ran out of time in this class, but because oci_fetch returns true if it succeeds in fetching a next row and returns false if it could not, a common pattern when asking that a query be executed that MIGHT select MULTIPLE rows is to use the call to oci_fetch as the bool expression in a while loop, to do something with each row selected: ...oci_connect... ...oci_parse... ...oci_execute... while (oci_fetch(...)) { ... ... oci_result ... ... oci_result ... ... } oci_free_statment(...); oci_close(...);