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
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-ui
command 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:
-
Or refresh the page opens, PV + 1
-
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 start
start
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 list
command 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.