PHP Institute of eight days day7 combat: the development of PV module

 

This chapter explains PHP developers PV modules. It took six days earlier, PHP will learn every aspect over and over, so now to verify the learning outcomes.

 

First, create a project

Our project is the separation of the front and rear end, front-end using react framework, where you will use the default react framework.

Create a server-side PHP project

According to the fourth day of the first study, we create a new laravel project.

Mapped into the directory vagrant virtual machine, create a project named blog laravel.

Due to network problems, this process will take some time before we can continue to do other things.

Homestead.yaml modify configuration files. Add a mapping sites options.

sites:
  - map: homestead.test
    to: /home/vagrant/code/Laravel/public
  - map: blog.test
    to: /home/vagrant/code/blog/public

Modify the hosts file to add a route map.

192.168.10.10 blog.test

Wait for the project to create a complete, restart the homestead configuration to take effect, executed under the root directory Homesteadvagrant reload --provision

Creating a front React project

To simplify the learning costs, we use the create-react-app to create react projects.

This assumes you have installed the npm, yarn and create-react-app environment.

Run craete-react-app blog-uicommand to create a project called blog-ui react of.

VSCode recommended to write front-end code.

 

Second, business needs analysis

PV is the What?

PV (Page View) visits that page views or clicks, a measure of the number of web sites they visit; open or refresh every user within a certain period of statistical records on a page once, several times or open the browser to refresh the same page the cumulative amount.

We conclude our look at the above content:

  1. Or refresh the page opens, PV + 1

  2. The same IP user, within a certain period of not more statistical PV amount, to prevent brush PV.

So what we need to do it?

Since my blog is not intended to open registration function, so the use of ip to record the user.

When you open the article, send a http get request, the request need only incidental article id, and user ip is to get through the back-end. These rear end of a data record to the redis and removed from redis the number of PV, as the return value to the requesting party. After receiving the distal appear on the page. Every 30 seconds and then reads the data written to the database thumbs do persistent storage from redis.

You may be in doubt, why not get the article data interface logic PV write it? The only advantage of doing so is to reduce a request. The downside is that no matter what the scenario, as long as the data access articles will record PV. For example, back office systems inside, get access to the article data interface, will still record PV, which would allow the interface to become highly coupled, can not reach the normal multiplexing.

In response, the industry's solution is micro-services, to achieve a variety of services through the combination of high-level API API service basis. We do not need to do so complicated.

Third, the data format design

redis supports five data structures, respectively, String, List, Set, Hash, Zset.

Our current business needs can use the most simple String storage. predis a corresponding api Let increment and decrement the number String value as the operation of the same.

Fourth, the back-end coding

Create a database

CREATE DATABASE IF NOT EXISTS blog DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

Create a table

CREATE TABLE `blog`.`Untitled`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `count` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

.Env modify the database configuration file

DB_DATABASE=blog

Installation predis in PHP projects

composer require predis/predis

Add in version prefix RouteServiceProvider.php

protected function mapApiRoutes()
    {
        Route::prefix('api/v1')
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }

Creating a controller

php artisan make:controller PVController  --invokable

PV inside the logic of the write record.

Maintenance redis two values, one is the combination of id values ​​each for detecting whether ip articles within 30 seconds and the other is a PV value of each blog.

public function __invoke(Request $request, string $id)
{
    $ip = $request->ip();
    $timeout_key = $ip . '@' . $id;
    $blog_pv_id = 'pv@' . $id;
    if (Redis::exists($timeout_key)) {
        if (time() - Redis::get($timeout_key) > 30) {
            if (Redis::exists($blog_pv_id)) {
                Redis::incr($blog_pv_id);
                Redis::set($timeout_key, time());
            } else {
                Redis::set($blog_pv_id, 1);
            }
        }
    } else {
        Redis::set($timeout_key, time());
    }
    return Redis::get($blog_pv_id);
}

Add Route

Route::get('getPV/{id}', 'PVController');

So far, the main logic code has been completed. It can be accessed from the browser, or to test the interfaces through professional testing tools.

 

Fifth, the front-end coding

First, write front-end code, install about routing and axios.

yarn add react-router-dom axios

Add in package.json configuration file proxy, cross-domain solve some problems.

"proxy": "http://blog.test/api/v1"

Creating pages directory under src, create a Home page and Blog page in the pages directory

Home page content:

import React from "react";
import { Link } from "react-router-dom";
export default function() {
  return (
    <div>
      Welcome to my website
      <Bloglist> </ bloglist>
    </div>
  );
}
// analog data about this 
function bloglist () {
   return (
     <UL>
      <li>
        <Link to="/blog/1">博客1</Link>
      </li>
      <li>
        <Link to="/blog/2">博客2</Link>
      </li>
    </ul>
  );
}

 

Blog page content:

import React from "react";
import PV from "../components/PV";
export default function(props) {
  const id = props.match.params.id;
  return (
    <div>
      i'm blog {id}
      <PV id={id}></PV>
    </div>
  );
}

 

Creating components directory under src, create PV modules in the components directory

PV module contents:

import React, { Component } from "react";
import Axios from "axios";
async function getPV(id) {
  return await Axios.get(`/getPV/${id}`);
}
export default class PV extends Component {
  state = {
    count: 0
  };
  componentDidMount() {
    getPV(this.props.id).then(res => {
      setState({ count: res.data });
    });
  }
  render() {
    return <div>阅读: {this.state.count}</div>;
  }
}

 

Create a file in the root directory router.js

import React from "react";
import { BrowserRouter, Route } from "react-router-dom";
import Home from "./pages/Home";
import Blog from "./pages/Blog";
export default function() {
  return (
    <BrowserRouter>
      <Route path="/" exact component={Home}></Route>
      <Route path="/blog/:id" component={Blog}></Route>
    </BrowserRouter>
  );
}

 

Modify App.js file.

import React from "react";
import Router from "./router";
function App() {
  return <Router></Router>;
}
export default App;

 

Running yarn startstart

Access HTTP: // localhost: 3000 / , click into a blog you can see the views.

 

Six, redis timing synchronization to Mysql

Create a scheduled task command. Commands to create a folder in the app / Console. File from which to create PVSynchronization.php

It reads as follows:

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
class PVSynchronization extends Command
{
    // custom command 
    protected $ = Signature 'PV-Synchronization' ;
     // Command Description 
    protected Description $ = 'Volume of the PV from the Timing Synchronization Redis to the MySQL Blog' ;
    // corresponding to the command execution code 
    public function handle ()
    {
        $keys = Redis::keys('pv@*');
        foreach ($keys as $key) {
            // here taken out before 17 characters because predis stored key, comes laravel_database_ prefix needs truncated 
            $ p_redis_key = substr ($ Key,. 17 , mb_strlen (Key $));
            COUNT $ = Redis :: GET ($ p_redis_key);
             // here is the interception of the first three characters @ pv 
            DB :: Update ( 'Update the above mentioned id = pv the SET, COUNT =??' ,
                [substr($p_redis_key, 3, mb_strlen($p_redis_key)), $count]);
        }
    }
}

 

Sign up regular tasks

In the app / Console / Commands / Kernel.php file, find the schedule method, we define the task to join in

protected function schedule(Schedule $schedule)
{
    // everyMinute expressed performed once per minute. 
    schedule- $> Command ( 'PV-Synchronization') -> everyMinute ();
}

 

Run php artisan listcommand to detect whether the registration is successful, see the command of our own definition it means that the registration was successful.

Finally, run php artisan schedule:run, you can make this task timed up and running.

At this point, a RESTful service program has been up and running. However, due to time reasons, some details of the design is not perfect. For example redis design, since each article id has produced a key, so access is easy, but when to use regular index key, it will cost a great performance. If there are enough articles, you will perform a lot of tasks at the timing of the update statement, which can cause performance problems, the solution is to use batch update. You can follow me that way, or according to their own thinking, to optimize the code. This is to enhance the technology is very helpful. Finally, we need to understand a truth: like porridge good code, you need to take the time to boil. If you only give us half a day to do this function, it is estimated will be posted to the production environment to achieve business with this version. The beginning may be no problem, but over time, gradually increasing data, this interface will become a slow interface. If the business is a very complex system, other interfaces rely on this data, it can cause problems such as data is not synchronized.

 

Seven summary

After six days of hard study, and finally from scratch, I learned how to use PHP to develop RESTful server program. If you start to learn with me from day 0, and spend a lot of time to practice, I can clearly tell you, you just look at some of the interview questions, you can go to the interview PHP engineer.

Guess you like

Origin www.cnblogs.com/luzhenqian/p/11441218.html