PHP imitation blog park personal blog database and interface design_PHP tutorial

WBOY
Release: 2016-07-20 11:16:41
Original
1110 people have browsed it

I have been learning PHP by myself for more than half a year, intermittently, but in the end I firmed up my mind and continued PHP, so I wrote this PHP blog to find a stable PHP job without asking for a high salary. , but looking for a place to take shelter. I can understand most English documents. I am not stupid and I love learning. If you are interested, please contact me! Come if you are sincere! qq:240382473
I will release all key codes and documentation instructions in 3-5 times, and all styles in the blog backend will be applied to the blog garden!

Description:

1. It does not completely adopt the MVC architecture, but the concept is like this. Because it is not possible to write a very stable MVC architecture.
2. JQUERY AJAX is almost never used because I am not very familiar with it and can’t use it freely. You can use AJAX for guestbooks, no problem.
3. There are several public classes, and other codes are all handwritten. Please point out any shortcomings. Thank you very much.
4. Criticism and guidance are welcome, but please give your reasons.

Closer to home: Let’s look at the database architecture first

The engines of these tables are all MYISAM, which is convenient for access. (The yellow key represents the primary key; the blue diamond represents a non-empty field; the white diamond represents a null field) The links in the picture only represent a potential relationship between them and cannot be associated during operation. Because the search engine is MyISAM . Therefore, joint queries and multi-table operations are required.

I will select the most important special fields in the post and category tables to explain in detail, and the others will be mentioned as important.
post:
post_id
category_id varchar(10) This is the category used to index blog posts. The category_id here is also a string type, so multiple categories can be set for each blog post.

type varchar(20) This field is used to distinguish between post, article, and diary; it can also be set to postDraft, articleDraft;

visiable Whether the blog post is visible

Other commonly used fields include title, content, creation time, last modification time, number of views, number of comments, tags, allowed comments, and some reserved fields.

category:
parent, count_child_number, count_parent_number for future expansion
type can set the categories of photo albums, blog posts, and diaries respectively
Other common fields such as name, description, creation time, visibility
comment:
address user IP
user_agent User browser type

Other fields are omitted...
Server Architecture
PHP5.4.2 + MYSQL 5.523 + APACHE 2.2.22 + Windows NT ARIST-PC 6.1 build 7600 (Windows 7 Home Basic Edition) i586 (local)
Blog Architecture

Backend directory:

Backend directory description:

assert stores various resources js, css, image
class stores our classes, commonly used classes such as database operation classes, paging classes, and most of our models. . .
extention stores extensions such as mce's rich editor
config stores our configuration information
templates stores all templates (smarty is not used)
upload stores photos and other files
There will be some similar controllers in the admin root directory, such as index.php, post.php, article.php, photo.php

Let’s take a look at admin/config/config.php

复制代码 代码如下:
ini_set( "display_errors", true );
date_default_timezone_set( "Asia/Shanghai" );
// root and direcotry separate
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(dirname(__FILE__)));

// database information
// need hash
define( "DB_USERNAME", "****" );
define( "DB_PASSWORD", '*****' );
define( "DB_NAME", "blog" );

// important directory
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );

// user imformation
define( "ADMIN_USERNAME", "admin" );
define( "ADMIN_PASSWORD", '$2a$08$wim8kpwHhAKa6MBSsGUMGOYfjkU1xvRKd4Fxwal.wj8dqFboCVSFawim8kpwHhAKa6MBSsGUMGO');
// hash and verified the password
function hasher($info, $encdata = false){
$strength = "08";
//if encrypted data is passed, check it against input ($info)
if ($encdata) {
if (substr($encdata, 0, 60) == crypt($info, "$2a$".$strength."$".substr($encdata, 60))) {
return true;
}else {
return false;
}
} else {
//make a salt and hash it with input, and add salt to end
$salt = "";
for ($i = 0; $i < 22; $i++) {
$salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 63), 1);
}
//return 82 char string (60 char hash & 22 char salt)
return crypt($info, "$2a$".$strength."$".$salt).$salt;
}
}

function __autoload($className) {
if (file_exists(ROOT . DS . 'classes' . DS . strtolower($className) . '.class.php')) {
require_once(ROOT . DS . 'classes' . DS . strtolower($className) . '.class.php');
} else {
/* Error Generation Code Here */
}
}



这里我们定义了一些基本常量,和几个函数。

__autoload() 函数加载 admin/class/ 中的所有类
用 hasher() 函数加密了一个 88位的 不可逆密码, 登录过程就是用config.php 中的常量和 hasher( ) 函数来进行验证。

来看我们的 admin/index.php 后台控制器 这个控制器主页 显示一些博客的相关数据

复制代码 代码如下:
require_once( "config/config.php" );
session_start( );
$action = isset( $_GET['action'] ) ? $_GET['action'] : "";
$username = isset( $_SESSION['username'] ) ? $_SESSION['username'] : "";

if ( $action != "login" && $action != "logout" && !$username ) {
login();
exit;
}

switch( $action ){
case "login" :
login( ) ;
break;

case "logout";
logout( );
break;

default :
admin( );
break;
}

function login( ){
$results['pageTitle'] = "Login Form";
// handle login
if( isset( $_POST['login'] ) ){
// we simple verify it from constant variable
// if we need to verify the user from database , do this later
// $user = new User ;
// $user->isValidateUser( $name, $password );

if ( $_POST['username'] == ADMIN_USERNAME && $_POST['password'] == hasher($_POST['password'], ADMIN_PASSWORD ) ){
// register a session data
$_SESSION['username'] = ADMIN_USERNAME ;
// location to admin page
header( "Location: index.php");
} else {
// Login failed: display an error message to the user
$results['errorMessage'] = "Incorrect username or password. Please try again.";
require( TEMPLATE_PATH . "/loginForm.php" );
}
} else {
require( TEMPLATE_PATH . "/loginForm.php" );
}
}

function admin( ){
$results['pageTitle'] = "Administrator Page";
require( TEMPLATE_PATH . "/admin.php" );
}

function logout( ){
$results['pageTitle'] = "Login Page";
unset( $_SESSION['username'] );
header( "Location: index.php ");
}



这个设计模式是从一个老外那里学的!

原理就是:
首先我们加载我们的config.php, 初始化session变量,获得 $action 这个重要变量的值;
然后我们判断 $action 和 $username 的值, 如果用户没有登录以及用户名为空,返回登录页面;
如 果用户正确输入了用户名和密码,则注册一个session 变量 $username,然后跳转到主页面 index.php, 这时我们会调用默认的 $action admin( ), 这个函数会加载一个模版admin.php;里面有个数组变量 $results['pageTitle'],以及我们的后台博客样式框架。
如果用户输入错了,则给出提示信息。

这个设计理念的核心就是, give {action} then {do something}
我们会在后面的代码中反复看到。

这个就是博客后台的框架样式,从博客园copy 来的,采用表格布局的,兼容的,可自定义其他样式的,简单的,实用的,可扩展的,完美后台框架。

这个样式在其他的浏览器中表现同样兼容,写这篇博文的时候,我已完成了部分功能。 下一篇:实现随笔,文章,日记 以及他们分类的CRUD。废话不多说了,上一篇有个核心概念就是 give action do something !

这篇我就用代码来解释这个概念是啥意思,先看我的 post.class.php . 这个文件是我们的数据层处理类。
 

简单介绍一下这个model 类,它继承了一个数据库基类来做crud 等常用操作, 每次初始化时就会初始化一个数据库对象 $db. 我们就用这个对象来操作我们的数据。
对于数据操作有2个重要方法 storePostFormValues( ) , storeDiaryFormValues( ),它们2个方法是数据流的开始。
还 有2个方法很有意思,addChildNumber( ), reduceChildNumber( ),  它们负责在插入或删除文档时的 一个暗箱操作。因为我的文档可以用多个分类,所以在操作文档的时候,要考虑到一个问题,就是 category 表中有个字段 记录了该分类下的 文档数量。所以要动态地改变这些数目的值。
下面配合 post.php 控制器,我们就可以开始我们数据的流程了(我的控制器还不是一个类,所以无法生成API文档。因为这还不是真正地MVC架构。)所以在MVC之前,这个也能更利于的理解MVC到底是神马东东,以及你自己如何去应用,写出自己的MVC。

以下的情形都是假设:

$action = "Give me a girlfriend from the sky!"; Let's pass in this controller and see what happens.

Copy code The code is as follows:
require_once( "config/config.php" );
session_start( );
$action = isset( $_GET['action'] ) ? $_GET['action'] : "";
$username = isset( $_SESSION['username'] ) ? $_SESSION['username'] : "";

if( !$username )
{
header("Location: index.php?action=login");
exit;
}

Here we have an important flow control statement switch, which means switch; so when the above $action = "Give me a girlfriend from the sky!"; when switch is passed in, there are only two possibilities, One is on and one is off. There is a bit of a pun here, and some students may see it. hey-hey!

Getting back to the topic: Take a look at how our switch switches these $actions on and off. It’s obvious that I won’t get a girlfriend from the sky, because there is no such switch in the controller, so I can only talk about the code.

Copy code The code is as follows:
switch( $action )
{
case "newPost" :
newPost( );
Break;

case "delete" :
         delete( ) ;
Break;

case "updatePost":
         updatePost( );
Break;

case "IsDraft":
listDraft( );
Break;

case "logout" :
Logout( );
Break;

case "isPost":
listPost( );
Break;

case "diffentCategoryPost":
        diffentCategoryPost( );
Break;

case "unCategory":
         unCategory( );
Break;

default:
listPost( );
Break;
}

Each switch should define a default switch, so that when we don’t have a girlfriend, we can ensure that we still have gay friends.
How to pass in action?
Let’s look at such a URL, which is the navigation of our background framework. Post.php?action=isPost This is a standard action. Each of our URLs is actually composed of these actions. You can also add other parameters to it. in our url, so that we can GET (get the values ​​of these variables) in the methods defined in the controller, and then we can have more control.
Okay, when this url reaches our controller, we receive the judgment and then turn on an isPost switch so that we can call the following methods. Think about turning on and off lights and computers. Switches are what we often do. .
Here we just changed the place.
OK. Let’s look at the following method for this switch.

Copy code The code is as follows:
function listPost( )
{
$results = array( );
$results['pageTitle'] = "Post List" ;
$results['path'] = "Essay";
// set the message
If ( isset( $_GET['error'] ) )
{
If ( $_GET['error'] == "InsertedFailed" ) $results['errorMessage'] = "Failed to add document";
If ( $_GET['error'] == "postDeleteFailed" ) $results['errorMessage'] = "Document deletion failed";
}
If ( isset( $_GET['status'] ) )
{
If ( $_GET['status'] == "changesSaved" ) $results['statusMessage'] = "The document is saved!";
If ( $_GET['status'] == "Deleted" ) $results['statusMessage'] = "The document has been deleted!";
If ( $_GET['status'] == "Inserted" ) $results['statusMessage'] = "You added a new document!";
If ( $_GET['status'] == "SaveToDraft" ) $results['statusMessage'] = "The document was saved to the draft box!";
}

// Browse documents by category
$db = MySQL::getInstance( );
$pagination = new Pagination;
$cat = new Category;
$results['categories'] = $cat->getCategoryList("post");

$pagination->countSQL = "select * from post where type = 'post' " ;
$db->Query( $pagination->countSQL );
$pagination->totalRecords = $db->RowCount( );
$records = $db->HasRecords( $pagination->rebuiltSQL( ) );
If( $records )
{
          $results['posts'] = $db->QueryArray( $pagination->rebuiltSQL( ) );
         require_once(TEMPLATE_PATH . "/post/post_list.php");
}
else
{
         require_once(TEMPLATE_PATH . "/post/post_list.php");
}

}

We define an array, $results = array(); The role of this array is obvious. It will save any data we get from the model, and can also save the special parameters of GET from the url. Then it will be displayed in the template included in our require_once(*****) below, and the path is defined in the path variable.

At the same time we will receive 2 prompt parameters,

error means that there is an error in the operation. It is inevitable for everyone, including computers. Everyone will make mistakes. The key is to admit it. Computers do a good job and they have the courage to admit their mistakes.

status; indicates status, which is a successful operation.

$pagination = new Pagination; This class is our pagination class. We pass in a total number to it, and then it will calculate the total number of pages. Each time it jumps to a page, it is equivalent to refreshing once, so everyone The method is to GET (obtain) the value of the page on the url in the constructor, so that we know the current page. At the same time, we regenerated the query statement, followed by a limiting statement, similar to limit $start (starting id), $offset (length); the principle is to give me 10 records starting from this id; I The setting is 10, you can also be more flexible.
$cat = new Category; This class will be discussed in detail later, and it is also a very important classification model. Here we simply obtain all categories under this type and display them in the sidebar. I have completed it. There are pictures and the truth!

In this way, our $results array stores all the data needed for our page. Okay, let's take a look at how our template is output.

复制代码 代码如下:
 
 
    
         <br>              博客后台管理
            
                       
        
    
            
                
                    
                
                
                    
                    
                
                
                    
                    
                
            

                        
操作

                    

                        

                

                
                 if( isset( $results['statusMessage'] )){echo $results['statusMessage'];}
if( isset( $results['errorMessage'] )){echo $results['errorMessage'];}
?>
                

 

    

         文章(主要用于转载,发布原创博文要通过“随笔”)
    

    
    
       if( isset( $results['posts'] )){
     echo <<             
                
                    
                    
                    
                                  
                    
                    
                

 EOB;
         foreach( $results['posts'] as $post ){
             $time = date("Y-m-d H:i:s", $post['create_time']);
             if( $post['status'] == "1" ){
                 $post['status']  = "发布";
             }    else {
                 $post['status']  = "未发布";
             }
             echo <<
                
                
                
                
                
                    
            
 EOB;
         }
             echo "

                         标题
                    

                         发布

                         状态
                    

                         评论
                    

                         页面

                         浏览
                    

                         操作
                    

                         操作
                    
{$post['title']} ({$time}){$post['status']}{$post['view_count']}{$post['comment_count']}编 辑删除
";               
             if( isset( $pagination) ){$pagination->createLinks( ) ;}
     } else {
         echo "当前无内容!";
     }

 ?>  

    

 


 

                        

                    

            

                
                
         
                    logout