1. Trang chủ
  2. » Công Nghệ Thông Tin

Tạo mạng xã hội với PHP - part 6 docx

10 241 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 3,53 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

/** * Create a new database connection * @param String database hostname * @param String database username * @param String database password * @param String database we are using *

Trang 1

Connecting to the database and managing connections

In order to connect to multiple databases, we need to maintain a record of the

different connections This can be done by storing each connection resource in

an array, keeping a record as to which of the items in this array is the active

connection When a query is executed, it will perform the query against the

currently active connection.

<?php

/**

* Database management / access class: basic abstraction

*

* @author Michael Peacock

* @version 1.0

*/

class Mysqldb {

/**

* Allows multiple database connections

* each connection is stored as an element in the array, and the

active connection is maintained in a variable (see below)

*/

private $connections = array();

/**

* Tells the DB object which connection to use

* setActiveConnection($id) allows us to change this

*/

private $activeConnection = 0;

/**

* Queries which have been executed and the results cached for

later, primarily for use within the template engine

*/

private $queryCache = array();

/**

* Data which has been prepared and then cached for later usage,

primarily within the template engine

*/

private $dataCache = array();

/**

* Number of queries made during execution process

*/

private $queryCounter = 0;

Trang 2

[ 33 ]

/**

* Record of the last query

*/

private $last;

/**

* Reference to the registry object

*/

private $registry;

/**

* Construct our database object

*/

public function construct( Registry $registry )

{

$this->registry = $registry;

}

To connect to the database, we pass the database server host, username, and

password and of course the name of the database we wish to connect to The

resulting connection is stored in our connections array, and the connection ID

(Array key) is returned.

/**

* Create a new database connection

* @param String database hostname

* @param String database username

* @param String database password

* @param String database we are using

* @return int the id of the new connection

*/

public function newConnection( $host, $user, $password, $database )

{

$this->connections[] = new mysqli( $host, $user, $password,

$database );

$connection_id = count( $this->connections )-1;

if( mysqli_connect_errno() )

{

trigger_error('Error connecting to host '.$this-

>connections[$connection_id]->error, E_USER_ERROR);

}

return $connection_id;

}

This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010

3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246

Download from www.eBookTM.com

Trang 3

When we need to swap between connections, for example, to look up data from

an external source, or authenticate against another system, we need to tell the

database object to use this different connection This is achieved through the

setActiveConnection method

/**

* Change which database connection is actively used for the next

operation

* @param int the new connection id

* @return void

*/

public function setActiveConnection( int $new )

{

$this->activeConnection = $new;

}

Executing queries

After a query is executed, we may wish to get the rows from the result of the query;

to allow us to do this, we simply store the result of the query in the classes $last

variable, so that it can be accessed by other methods.

/**

* Execute a query string

* @param String the query

* @return void

*/

public function executeQuery( $queryStr )

{

if( !$result = $this->connections[$this->activeConnection]-

>query( $queryStr ) )

{

trigger_error('Error executing query: ' $queryStr ' -

'.$this->connections[$this->activeConnection]->error,

E_USER_ERROR);

}

else

{

$this->last = $result;

}

}

Trang 4

[ 35 ]

When we do need to get the results from a query, we simply call the MySQLi fetch_

array method on the result stored in the last variable

/**

* Get the rows from the most recently executed query, excluding

cached queries

* @return array

*/

public function getRows()

{

return $this->last->fetch_array(MYSQLI_ASSOC);

}

Simplifying common queries

Common queries such as INSERT, UPDATE, and DELETE are often very repetitive;

however, they are quite easy to abstract the basics of into our database management

class This won't work for all situations, but should make our lives easier for the

bulk of these operations We can abstract select queries to this class too However,

these are much more complicated, particularly, as we will more often than not, need

to utilize more complicated logic, such as sub-queries, joins, and aliases This more

complicated logic would need to be developed into the code.

Deleting records can be done simply using the table name, conditions, and a limit In

some cases, a limit may not be required, so if a non-empty string is passed, we need

to add the LIMIT keyword to the query.

/**

* Delete records from the database

* @param String the table to remove rows from

* @param String the condition for which rows are to be removed

* @param int the number of rows to be removed

* @return void

*/

public function deleteRecords( $table, $condition, $limit )

{

$limit = ( $limit == '' ) ? '' : ' LIMIT ' $limit;

$delete = "DELETE FROM {$table} WHERE {$condition} {$limit}";

$this->executeQuery( $delete );

}

This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010

3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246

Download from www.eBookTM.com

Trang 5

Updating and inserting records are tasks I find to be the most cumbersome; however,

we can easily abstract these simply by passing the table name, an array of field

names and field value pairs, and in the case of update operations, a condition.

/**

* Update records in the database

* @param String the table

* @param array of changes field => value

* @param String the condition

* @return bool

*/

public function updateRecords( $table, $changes, $condition )

{

$update = "UPDATE " $table " SET ";

foreach( $changes as $field => $value )

{

$update = "`" $field "`='{$value}',";

}

// remove our trailing ,

$update = substr($update, 0, -1);

if( $condition != '' )

{

$update = "WHERE " $condition;

}

$this->executeQuery( $update );

return true;

}

/**

* Insert records into the database

* @param String the database table

* @param array data to insert field => value

* @return bool

*/

public function insertRecords( $table, $data )

{

// setup some variables for fields and values

$fields = "";

$values = "";

// populate them

Trang 6

[ 37 ]

foreach ($data as $f => $v)

{

$fields = "`$f`,";

$values = ( is_numeric( $v ) && ( intval( $v ) == $v ) ) ?

$v."," : "'$v',";

}

// remove our trailing ,

$fields = substr($fields, 0, -1);

// remove our trailing ,

$values = substr($values, 0, -1);

$insert = "INSERT INTO $table ({$fields}) VALUES({$values})";

//echo $insert;

$this->executeQuery( $insert );

return true;

}

Sanitizing data

Depending on the exact PHP setup, data needs to be sanitized slightly differently,

to prevent characters being escaped too many times This is often the result of

magic_quotes_gpc setting To make things easier, and to provide a single place

for changes to be made depending on our server's configuration, we can centralize

our data sanitization.

/**

* Sanitize data

* @param String the data to be sanitized

* @return String the sanitized data

*/

public function sanitizeData( $value )

{

// Stripslashes

if ( get_magic_quotes_gpc() )

{

$value = stripslashes ( $value );

}

// Quote value

if ( version_compare( phpversion(), "4.3.0" ) == "-1" )

{

$value = $this->connections[$this->activeConnection]-

This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010

3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246

Download from www.eBookTM.com

Trang 7

>escape_string( $value );

}

else

{

$value = $this->connections[$this->activeConnection]-

>real_escape_string( $value );

}

return $value;

}

Wrapping other MySQLi functions

This leaves us with a few other common MySQLi functions to wrap into our class,

including fetching the data from the executed query, fetching the number of rows

returned by a query, and getting the number of rows affected by a query.

/**

* Get the rows from the most recently executed query, excluding

cached queries

* @return array

*/

public function getRows()

{

return $this->last->fetch_array(MYSQLI_ASSOC);

}

public function numRows()

{

return $this->last->num_rows;

}

/**

* Gets the number of affected rows from the previous query

* @return int the number of affected rows

*/

public function affectedRows()

{

return $this->last->affected_rows;

}

Trang 8

[ 39 ]

Disconnecting

When the database object is no longer required, we should disconnect from all of the

connections we have made to various databases This can be done through a simple

foreach loop in the deconstructor

/**

* Deconstruct the object

* close all of the database connections

*/

public function deconstruct()

{

foreach( $this->connections as $connection )

{

$connection->close();

}

}

}

?>

Template management

Template management is another set of core tasks that will need to be accessed by

almost every aspect of our social network code Every page request needs to display

something to the user, and for each user the page will normally be different, and

contain dynamic data from our database.

For example, when any user views their friends list, they will all see the same page

layout; however, the list of friends will be different When they view a profile, all

profiles will have the same layout, with different data, and in some cases, some

additional sections to the page, depending on how complete their profile is.

Our template manager should take a series of template files, which contain the

HTML to be sent to the browser, and manage data, which should be inserted

into it, as well as process this dynamic replacement of data.

Additional templates should be able to be included within a template, should they

be required—for instance when viewing the profile of a user who has comments

enabled, a comments list and form should be displayed, whereas a user without this

would not see a list of a comments form.

The data and template contents will be stored in a Page object; the management of

this object and its processing will be handled by the template object Let's go through

what we need in our template class (registry/template.class.php).

This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010

3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246

Download from www.eBookTM.com

Trang 9

Firstly, we need to create the object, which involves assigning our registry to a

variable, including the page class, and instantiating a page object.

/**

* Include our page class, and build a page object to manage the

content and structure of the page

* @param Object our registry object

*/

public function construct( Registry $registry )

{

$this->registry = $registry;

include( FRAMEWORK_PATH '/registry/page.class.php');

$this->page = new Page( $this->registry );

}

Since the views are made up of a number of template files, we need to be able to

include these files and send them to our page object Certain pages might be made

up of two templates, others may be made up of three or more To make this flexible,

instead of defining parameters for this method, we instead take however many

templates are passed as parameters and include them, in order, to our page object.

/**

* Set the content of the page based on a number of templates

* pass template file locations as individual arguments

* @return void

*/

public function buildFromTemplates()

{

$bits = func_get_args();

$content = "";

foreach( $bits as $bit )

{

if( strpos( $bit, 'views/' ) === false )

{

$bit = 'views/' $this->registry->getSetting('view') '/

templates/' $bit;

}

if( file_exists( $bit ) == true )

{

$content = file_get_contents( $bit );

}

}

$this->page->setContent( $content );

}

Trang 10

[ 41 ]

Within our template files, we may need to insert other templates For instance, as

we mentioned earlier, if one user has comments enabled on their profile, and another

doesn't, then they will use the same main template, however, different templates will

be inserted dynamically into them.

We can do this by taking a $tag (which is something contained within the template

already included), and a template $bit, which is included and placed within the

main template where the $tag was found.

/**

* Add a template bit from a view to our page

* @param String $tag the tag where we insert the template e.g

{hello}

* @param String $bit the template bit (path to file, or just the

filename)

* @return void

*/

public function addTemplateBit( $tag, $bit )

{

if( strpos( $bit, 'views/' ) === false )

{

$bit = 'views/' $this->registry->getSetting('view') '/

templates/' $bit;

}

$this->page->addTemplateBit( $tag, $bit );

}

These templates bits that we insert into our page object need to actually be replaced

into the current page, which is where the replaceBits method comes in This iterates

through the list of template bits, and performs the replacement The replacement is

done in order, so if we wanted to insert a template into a page, and then insert another

template into that one, we can do, so long as they were added in order.

The replacement is a simple str_replace to find the tag, and replace it with the

contents from the template.

/**

* Take the template bits from the view and insert them into our page

content

* Updates the pages content

* @return void

*/

private function replaceBits()

{

$bits = $this->page->getBits();

// loop through template bits

This material is copyright and is licensed for the sole use by RAYMOND ERAZO on 25th October 2010

3146 KERNAN LAKE CIRCLE, JACKSONVILLE, 32246

Download from www.eBookTM.com

Ngày đăng: 04/07/2014, 21:20