Neste artigo, criaremos um painel que pode exibir gráficos a partir de dados em tempo real. Os dados que usamos como simulações são a população de uma cidade. Se você atualizar os dados dos residentes, adicioná-los ou excluí-los, o gráfico será alterado em tempo real sem a necessidade de atualizar a página.
Antes de começarmos, precisamos nos preparar:
- Webserver está instalado, consulte Como configurar o Virtual Host XAMPP no Windows 10
. - O Yii2 está instalado, consulte Como instalar o Yii2 Advanced via Composer
. - O Node.js já está instalado, consulte Criar aplicativos em tempo real com o Nodes.js
. - Chart.js.
Etapas para criar um painel de controle de aplicativo em tempo real com Yii2, Node.js, MySQL e Chart.js
A. Criar uma tabela com o MySQL
Crie tabelas com o nome “city” e colunas com os nomes “id” e “population”. Ou é mais fácil executar os seguintes scripts sql.
CREATE TABLE 'city' (
'id' CHAR(16) NOT NULL PRIMARY KEY,
'population' INT(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
B. Criar um servidor Node.js
- Configure um servidor Node.js como em Criando aplicativos em tempo real com Nodes.js.
- No arquivo “server.js”, o que precisamos criar é uma “API” que atualizará os dados no gráfico que criamos com o Chart.js depois que os dados forem armazenados com sucesso pelo Yii.
- Quando o usuário abre a página do painel pela primeira vez, verificamos se os dados iniciais do gráfico do painel estão disponíveis; caso contrário, o Yii enviará os dados iniciais.
app.post('/status', (req, res) => {
res.send(isInitData);
});
app.post('/initData', (req, res) => {
if(!isInitData){
myData = req.body;
isInitData=true;
}
res.send('success');
});
- Em seguida, criaremos uma “API” que atualizará os dados sobre as operações de crud no Yii.
app.post('/newData', (req, res) => {
switch (req.body.actions){
case "create":
myData.push({id: req.body.id, population: req.body. population});
break;
case "update":
let i = myData.findIndex(label => label.id === req.body.id);
myData [i] ={id: req.body.id, population: req.body. population};
break;
case "delete":
let l = myData.findIndex(label => label.id === req.body.id);
myData.splice(l,1);
break;
}
io.emit('newData', {id: req.body.id, population: req.body. population, actions:req.body.actions});
res.send('success');
});
- Script completo do arquivo server.js
var app = require("express")();
var bodyParser = require('body-parser')
var http = require('http'). Server(app);
var io = require("socket.io")(http,{cors: {origin:"*"}});
var myData = [] ;
var isInitData=false;
http.listen(3000, function () {
console.log("Listening on 3000");
});
app.use(bodyParser.json({type: 'application/json' }));
app.post('/status', (req, res) => {
res.send(isInitData);
});
app.post('/initData', (req, res) => {
if(!isInitData){
myData = req.body;
isInitData=true;
}
res.send('success');
});
app.post('/newData', (req, res) => {
switch (req.body.actions){
case "create":
myData.push({id: req.body.id, population: req.body. population});
break;
case "update":
let i = myData.findIndex(label => label.id === req.body.id);
myData [i] ={id: req.body.id, population: req.body. population};
break;
case "delete":
let l = myData.findIndex(label => label.id === req.body.id);
myData.splice(l,1);
break;
}
io.emit('newData', {id: req.body.id, population: req.body. population, actions:req.body.actions});
console.log("issuer new data "+req.body.id+" :"+req.body.actions);
res.send('success');
});
io.on("connection", (socket) => {
console.log("A user is connected");
if(isInitData){
console.log("initial data issuer");
socket.emit('initialData', myData);
}
});
Outros artigos interessantes
C. Configuração no Yii2
- Crie uma classe “myCurl.php” com a função “CurlToNodejs”. Para saber como criar uma função, consulte [Yii2] How to create and use Functions in Yii2 Basic and Advanced Templates.
class myCurl extends Component
{
public function CurlToNodejs($url.$postdata=null)
{
$header = ['Content-type: application/json'] ;
$curl = curl_init();
curl_setopt ($curl, CURLOPT_URL, $url)
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
$response = curl_exec($curl);
return $response;
}
}
- Depois disso, criamos uma visualização “myChart.php” para exibir os gráficos do painel. Para usar o chart.js, você pode vê-lo em www.chartjs.org
<?php
/* @var $this yiiwebView */
$this->title = 'My Chart Application';
$script = < JS
$(document).ready(function(){
//Chart.js Configuration
const data = {
datasets: [{
label: 'My First Dataset',
borderWidth: 1
}]
};
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
type: 'bar',
data: data,
});
function UpdateChart(chart, label, data) {
chart.data.labels=label;
chart.data.datasets.forEach((dataset) => {
dataset.data=data;
});
chart.update();
}
Socket.io Configuration
const socket = io.connect( 'http://localhost:3000');
var labels = [] ;
var values = [] ;
socket.on('initialData', function(data){
for (let i = 0; i < data.length; i++){
labels [i] = [i] (.id data);
values [i] = [i] (.population data);
}
UpdateChart(myChart,labels,values);
});
socket.on('newData', function(data){
switch (data.actions){
case "create":
const i = labels.length;
labels [i] = data.id;
values [i] = data.population;
break;
case "update":
const l = labels.findIndex(label=>label===data.id);
values [l] = data.population;
break;
case "delete":
const x = labels.findIndex(label=>label===data.id);
if (x > -1) {
labels.splice(x, 1);
values.splice(x, 1);
}
break;
}
UpdateChart(myChart,labels,values);
});
});
JS;
$this->registerJs($script);
$this->registerJsFile("https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js",); ['position' => yiiwebView::POS_HEAD]
$this->registerJsFile('https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js', ['position' => yiiwebView::POS_HEAD] );
?><div class="site-index">
<div class="body-content">
<div id="container" style="width: 75%;">
<canvas id="myChart"></canvas>
</div>
</div>
</div>
Em “SiteController.php”, adicionamos “actionMychart”. Nessa função, verifique se os dados iniciais estão disponíveis ou não. Caso contrário, será feita uma consulta ao banco de dados como os dados iniciais.
public function actionMychart()
{
$response = Yii::$app->myCurl->CurlToNodejs('http://localhost:3000/status');
if ($response === 'false') {
$data = commonmodelsCity::find()
->asArray()
->all();
$response 1 = Yii::$app->myCurl->CurlToNodejs('http://localhost:3000/initdata', json_encode($data));
}
return $this->render('myChart');
}
- Até esta etapa, já podemos exibir gráficos do painel. No entanto, não foi possível exibir alterações de dados. Desta vez, usaremos o “Gii” para fazer CRUD. Para obter mais detalhes, você pode consultar o Gerando código com Gii.
- Crie um modelo “City” com um “Gii Generator Model”. A partir dessa etapa, será formado um arquivo “/models/City.php”.
- Em seguida, crie-o com o “CRUD Generator Gii” a partir do modelo. A partir dessa etapa, os seguintes arquivos serão formados.
![nodejs yii2 mysql chartjs 01](https://bardimin.com/wp-content/uploads/2021/09/nodejs-yii2-mysql-chartjs-01.jpg)
- A próxima etapa é adicionar um script ao “CityController.php” que notificará o Node.js sobre as alterações de dados usando a função “myCurl” que criamos anteriormente.
- Altere “actionCreate” para o seguinte
public function actionCreate()
{
$model = new City();
if ($this->request->isPost) {
if ($model->load($this->request->post()) && $model->save()) {
$post=Yii::$app->request->post('City');
$data = ["id" => $post['id'] , "population" = > $post ['population'] "actions"=> "create"];
Yii::$app->myCurl->CurlToNodejs('http://localhost:3000/newData',json_encode($data));
return $this->redirect; ['view', 'id' => $model->id]
}
} else {
$model->loadDefaultValues();
}
return $this->render('create', [
'model' = > $model,
]);
}
- Em seguida, altere “actionUpdate” para o seguinte
public function actionUpdate($id)
{
$model = $this->FindModel($id);
if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
$post=Yii::$app->request->post('City');
$data= , ["id" => $post['id'] "population" = > $post ['population'] "actions"=>"update"];
Yii::$app->myCurl->CurlToNodejs('http://localhost:3000/newData',json_encode($data));
return $this->redirect; ['view', 'id' => $model->id]
}
return $this->render('update', [
'model' = > $model,
]);
}
- E, em seguida, altere “actionDelete” para o seguinte
public function actionDelete($id)
{
$this->findModel($id)->delete();
$data = ["id" => $id, "population" =>"","actions"=>"delete"] ;
Yii::$app->myCurl->CurlToNodejs('http://localhost:3000/newData',json_encode($data));
return $this->redirect; ['index']
}
D. Executar um aplicativo
- Execute o Node server.js com
node server.js
- Se todos os processos estiverem corretos, você verá isso dessa forma.
![nodejs yii2 mysql chartjs](https://bardimin.com/wp-content/uploads/2021/09/nodejs-yii2-mysql-chartjs.gif)