Showing live CPU usage via WMI with PHP and Ajax - php

Is there any alternative to a persistent connection with just Apache/PHP than setting up another server with WebSockets/Node.js?
At the current moment, I'm running a typical WAMP server with a Laravel application. This laravel application is a sort of dashboard app which can show details (such as CPU/Network usage) of our servers on the network. This application will only be used by a couple of people at a time (it's internal) so it allows me to be quite flexible with performance.
I'm using the COM library in PHP to query the server for information via WMI. I have it set up by using a typical GET route that returns a json string of the CPU usage in percentage of the server from WMI. This is getting refreshed every single second using setInterval().
Though obviously this is immense load on the server, and CPU goes through the roof when seeing the usage of a network PC.
A picture is below showing what my app looks like. The progress bar will fill to the percentage returned when the ajax request completes. It looks good and works well, but I feel like running an ajax request every single second is bad design, and really want something that can just constantly feed the progress bar rather than request a new value from the server.
Please let me know if you need any code/examples of my current progress. Thanks!
Code as requested:
My route:
Route::get('{machine_id}/{field?}', array('as'=>'admin.computer.view.detailed', 'uses'=>'ComputerController#getViewDetailed'));
My Controller:
public function getViewDetailed($computer_id, $field = NULL){
$computer = $this->machine->find($computer_id);
if($computer){
if(!$computer->type->type_name == 'Servers'){
return Redirect::route('admin.computer.index');
} else{
if($field){
switch($field){
case 'cpu':
return Response::json(Network::get_cpu_info($computer->machine_name));
break;
case 'temp':
return Response::json(Network::get_temp_info($computer->machine_name));
break;
case 'tcp':
return Response::json(Network::get_tcp_info($computer->machine_name));
break;
}
}
$disks = Network::get_disk_info($computer->machine_name);
$memory = Network::get_memory_info($computer->machine_name);
$cpu = Network::get_cpu_info($computer->machine_name);
$tcp = Network::get_tcp_info($computer->machine_name);
$this->layout->title = 'Viewing Server Details for: '.$computer->machine_name;
$this->layout->content = View::make('computers.templates.view.detailed')
->with('computer', $computer)
->with('disks', $disks)
->with('memory', $memory)
->with('cpu', $cpu)
->with('tcp', $tcp);
}
} else{
return Redirect::route('admin.computer.index')
->with('message', Lang::get('custom.messages.computers.errors.exist'))
->with('color','danger');
}
}
My class requesting WMI Information:
class Cpu {
public static $com_namespace = 'root\\cimv2';
private $query = 'SELECT Name, CurrentClockSpeed, LoadPercentage From Win32_Processor';
private $cpu = array();
public function info($service, $pc){
$this->cpu = $service->ExecQuery($this->query);
return $this->format($this->cpu);
}
public function format($cpu){
$formatted_cpu = array();
$i = 0;
foreach($cpu as $entry){
$formatted_cpu[$i]['name'] = $entry->Name;
$formatted_cpu[$i]['current_clock_speed'] = $entry->CurrentClockSpeed;
$formatted_cpu[$i]['load'] = $entry->LoadPercentage;
$i++;
}
return $formatted_cpu;
}
}
My View:
#if($cpu)
<script type='text/javascript'>
$(document).ready(function(e) {
function getCpu(){
$('.server').each(function(index, element) {
var server = $(this);
var url = $(this).attr('data-url');
var panel = $(this).find('.panel');
var progress_bar = $(this).find('.progress-bar');
$.ajax({
url: url,
type: 'GET',
dataType:"json",
success: function(response){
if(response){
$(progress_bar).html(response[0]['load']+"%").attr('aria-valuenow', response[0]['load']).css('width', response[0]['load']+"%");
if(response[0]['load'] > 50){
$(panel).removeClass('panel-default').addClass('panel-danger');
} else{
$(panel).removeClass('panel-danger').addClass('panel-default');
}
} else{
$(server).css('display', 'none');
}
}
});
});
}
setInterval(getCpu, 1000);
});
</script>
<div data-url="{{ route('admin.computer.view.detailed', array($computer->id, 'cpu')) }}" class="server">
<div class="panel panel-default">
<div class="panel-heading text-center">CPU Load</div>
<div class="panel-body">
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</div>
</div>
</div>
#endif

Related

How to delete data from DB using React, and hitting a rest API that i created using php and mysql?

The api works fine because I already tested it in postman, and I've managed to create the front end and show all the data stored in my api, now I want to press a button and delete the particular item I want.
When I press the delete button, an alert pops up with the id of the current item, so I know passing the id isn't an issue. The problem is when I use the fetch function.
Here's the delete function from my api:
public function delete(){
//crear query
$query = 'DELETE FROM ' . $this->table . ' WHERE ID = :ID';
//prepare statement
$stmt = $this->conn->prepare($query);
//clean data
$this->ID = htmlspecialchars(strip_tags($this->ID));
//bind data
$stmt->bindParam(':ID', $this->ID);
//execute query
if($stmt->execute()){
return true;
}
//print error if something goes wrong %s es un placeholder
printf("Error: %s. \n", $stmt->error);
return false;
}
Here's the react code (check the function handleBorrar):
import React from 'react';
class Pelicula extends React.Component{
constructor(props){
super(props);
this.state={
loading:true,
pelicula:null,
};
}
async handleBorrar(id) {
alert(`hello, ${id}`);
const responseDel = await fetch(`http://localhost/APIpeliculas/api/pelicula/read.php/${id}`, {
method: "DELETE",
});
return responseDel.json();
}
async componentDidMount(){
const url = "http://localhost/APIpeliculas/api/pelicula/read.php";
const response = await fetch(url);
const result = await response.json();
this.setState({pelicula:result.data, loading: false});
document.body.style.backgroundColor = "burlywood";
}
render(){
if (this.state.loading){
return <div> loading... </div>
}
if(!this.state.pelicula){
return <div> Sin peliculas... </div>
}
return(
<div className="container">
<div className="row">
{
this.state.pelicula.map((peli, index)=>{
return(
<div key = {index} className="col-sm-12 col-md-6 col-lg-4 mt-3 d-flex justify-content-center col-style">
<div className="card card-style">
<div className="card-body">
<h5 className="card-title">{peli.Nombre}</h5>
<h6 className="card-subtitle mb-2 text-muted">{peli.Categoria}</h6>
<p className="card-title"> {peli.Director} </p>
<button type="button" className="btn btn-labeled btn-danger" onClick={() => this.handleBorrar(peli.ID)}> Borrar </button>
<button type="button" className="btn btn-labeled btn-warning"> Editar </button>
</div>
</div>
</div>
)
})
}
</div>
</div>
)
}
}
export default Pelicula;
I got some ideas for the fetch DELETE method by reading another questions from here, but I'm not sure how it will work. What is the json that will return? Also, will react render everything again and call the api to update everything or will I have to reload the page to see the results?
Also, I'm not sure if I'm using the right url, since when I made the api and tested it in postman, to delete and item I have to use the url: http://localhost/APIpeliculas/api/pelicula/delete.php and then pass the ID on the body as a JSON object. So I'm not sure how will it work, since the route for my api won't take a delete.php/ID route.
If you're using a RESTful API, there's no mandatory response when you delete a resource successfully. You can return status 204 when the resource is deleted and some of the 400 statuses when something goes bad. See this question for suggestions. You don't even need to get the body of the request, as you are not using it anyway.
If an item has been deleted from DB, it makes sense to also remove it from your view. You can do so by refreshing the page (not a good idea), by reloading the list or by filtering the array, as in:
removeById = (id) => {
this.setState((state) => ({
pelicula: state.pelicula.filter((item) => item.id !== id)
}));
};
async handleBorrar(id) {
alert(`hello, ${id}`);
try {
const responseDel = await fetch(
`http://localhost/APIpeliculas/api/pelicula/read.php/${id}`,
{
method: "DELETE"
}
);
if (!responseDel.ok) throw new Error("API request not ok");
if (responseDel.status >= 400 && responseDel.status < 600) {
throw new Error("Bad response from server");
}
this.removeById(id);
} catch (error) {
// do something with the error, maybe warn the user
}
}

Why doesn't ng-repeat update dynamically?

I've literally checked out every single ng-repeat question out there but a lot of them don't deal with databases and people just use arrays in JS and a simple $scope.array.push("stuff") works for them.
I've tried $scope.apply, $rootScope and even calling the GET request right after a successful POST request.
I have a form with 2 text inputs, date and content.
When the submit button is pressed, date and content are added into a MySQL database using PHP.
The data is added just fine to the MySQL database and retrieving also works properly.
Even the GET request inside the successful POST request is executed.
So I don't understand why it forces me to refresh the page to see the updated ng-repeat results.
Am I missing something?
Any help or suggestions is greatly appreciated, thanks!
Relevant HTML code
<div ng-controller="insertController">
<h2> What I learned today </h2>
<form>
Date <br>
<input type="text" ng-model="date"><br><br>
Content <br>
<textarea rows="10" cols="50" ng-model="content"></textarea><br><br>
<input type="button" value="Submit" ng-click="insertdata()">
</form>
</div>
<div ng-controller="fetchController">
<span ng-repeat="item in results">
{{item.date}}<br>
{{item.content}}<br><br>
</span>
</div>
insertController.js
var app = angular.module('myApp', []);
app.controller('insertController', function($scope, $http) {
$scope.insertdata = function() {
$http({
method: 'POST',
url: 'http://localhost/storestuff/insert.php',
data: {'date':$scope.date, 'content':$scope.content, 'in':'json-format'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.then(function(res) {
console.log("Successful response", res)
$scope.date = "";
$scope.content = "";
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
alert("GOT NEW DATA");
$scope.results = response.data; // Allow angular to access the PHP output data
});
$scope.apply;
})
.catch(function(err) {
console.error("Error with POST", err);
});
}
});
insert.php
<?php
header('Access-Control-Allow-Origin: *');
$theConnection = mysqli_connect("localhost", "root", "", "storestuff");
if(mysqli_connect_errno()) {
echo "Failed to connect to MySQL.";
}
$theData = json_decode(file_get_contents('php://input'));
$date = mysqli_real_escape_string($theConnection, $theData->date);
$content = mysqli_real_escape_string($theConnection, $theData->content);
mysqli_query($theConnection, "INSERT INTO thestuff(date, content) VALUES('$date', '$content')");
mysqli_close($theConnection);
?>
fetchController.js
app.controller('fetchController', function ($scope, $http) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
$scope.results = response.data; // Allow angular to access the PHP output data
});
});
fetch.php
<?php
header('Access-Control-Allow-Origin: *'); // clientside(Node) <-> serverside(PHP)
$mysqli = new mysqli("localhost", "root", "", "storestuff");
if($mysqli->connect_error) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$query = "SELECT * FROM thestuff";
$theData = array();
if($result = $mysqli->query($query)) {
while($row = mysqli_fetch_array($result)) {
$theData[] = array(
'date'=>$row['date'],
'content'=>$row['content']);
}
echo json_encode($theData); // Echo the output for the controller to access
$result->free(); // Free the result set
}
else {
echo "0 results.";
}
$mysqli->close(); // Close the connection
?>
The problem with this code is that you have two different controllers, both with separate scopes. Inserting/updating the $scope.results object/array in one controller, will not update the other $scope; they are separate distinct scopes, both with a copy of the data.
Using two controllers looks correct in your use case. However you should be using a service to access your remote data. Check out this answer for some advice on this https://stackoverflow.com/a/20181543/2603735.
Using a service like in that answer, will allow you to store the array/object of remote data in one place, and reference the SAME object from both controllers. Therefore updating from one controller, will also update the other.
For anyone who will ever stumble on my question, I don't want to just leave my broken code there with no answer but neither can I edit the question and put in my answer cause that would defy the purpose of StackOverflow.
So here is my answer to my own question.
I had to make quite a few changes to what I had before. The biggest change by far, is how I handled the data that was returned by fetch.php.
Instead of just taking the output into $scope.results = response.data;, which would work fine if I wasn't dynamically adding to the database, but for this case, I ended up using a service. (Thanks #jayden-meyer for suggesting Angular services.)
The service allowed me to access the same array from my insertController and from my fetchController instead of having a copy of the same array in both controllers which was my problem.
No changes in the HTML code.
No changes to insert.php.
No changes to fetch.php.
insertController.js
I removed the extraneous GET request I had inside the .then method which was completely unneeded since I can just push to the existing array.
(Thanks #charlietfl for the tip)
Instead I added resultsService.addItem($scope.date, $scope.content); inside of the .then method.
I also added my service as an argument.
app.controller('insertController', function($scope, $http, resultsService) {
result.js
app.service('resultsService', function() {
var results = new Array();
var addItem = function(date, content) {
var obj = new Object();
obj["date"] = date;
obj["content"] = content;
results.push(obj);
}
var getItems = function() {
return results;
}
return {
addItem: addItem,
getItems: getItems
};
});
fetchController.js
var size = 0;
var count = 0;
app.controller('fetchController', function ($scope, $http, resultsService) {
$http.get('http://localhost/storestuff/fetch.php')
.then(function successCallback(response) {
size = (response.data).length;
while(count < size) {
var date = response.data[count].date;
var content = response.data[count].content;
resultsService.addItem(date, content);
count++;
}
size = 0;
count = 0;
$scope.results = resultsService.getItems();
});
});

Laravel with angularJS load template after $http call

I am using Laravel with AngularJs trying to fetch data using $http method of angularJS
I got data successfully but the problem is that I want to redirect to another page to show the result how can I achieve this using AngularJs?
Here is my jobs.js controller
app.controller('JobsController', function($scope, homepagesearchService) {
$scope.opts = [];
$scope.city = ["All", "Dubai", "Abu Dhabi", "sharjah", "ras al khaimah", "ajman", "umm al quwain", "fujairah", "Al Ain"];
for (var i = 0; i <= 30; i++) {
$scope.opts.push(i);
}
$scope.homepageSearch = function(search) {
homepagesearchService.getData(search).then(function(data) {
$scope.result = data;
console.log(data);
});
}
});
A service to get data from database
angular.module('jobs').factory('homepagesearchService', function($http){
return {
getData: function(search){
if(angular.isUndefined(search.keyword)){
search.keyword = 'search-job';
}
return $http({
method : 'POST',
url : '/search/'+angular.lowercase(search.keyword).replace(/[^a-zA-Z0-9_]/g,'-')+'-'+'jobs',
data : search, //forms user object
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function(result){
return result.data;
});
}
}
});
JobsController from where I got the data
<?php
/*
*Developer: Kritika Shrivastava
*Jobs Controller to Fetch All Jobs
*
*/
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Jobs;
class JobsController extends Controller
{
/**
* Show the application welcome.
*
* #return \Illuminate\Http\Response
*/
public function welcome(){
return view('welcome');
}
/*
*
*Ajax Call to search Home Page
*
*/
public function homepageSearch(){
$_POST = json_decode(file_get_contents('php://input'), true);
$jobs = Jobs::latest('created_at')->search()->get();
echo $jobs;
}
}
This is my search form
#extends('layouts.app')
#section('content')
<div ng-app="jobs">
<div class="m-banner-1" ng-controller="JobsController">
<div class="main ui container m-banner-1-cover" >
<form ng-submit="homepageSearch(search)">
<div class="ui grid">
<div class="sixteen wide mobile five wide tablet five wide computer column auto-k">
<p style="color:#ffffff;font-size:20px;">Enter Keywords</p>
<div class="ui fluid icon input">
<input type="text" placeholder="Search a very wide input..." ng-model="search.keyword">
</div>
</div>
<div class="sixteen wide mobile five wide tablet five wide computer column ui fluid">
<p style="color:#ffffff;font-size:20px;">Location</p>
<select class="ui fluid normal dropdown"
ng-options="cit for cit in city" ng-model="search.city">
</select>
</div>
<div class="sixteen wide mobile five wide tablet five wide computer column">
<p style="color:#ffffff;font-size:20px;">Experience</p>
<select class="ui fluid normal dropdown" ng-model="search.experience"
ng-options="opt as opt for opt in opts">
<option value="">Years</option>
</select>
</div>
<div class="sixteen wide column align center">
<button class="ui massive button orange-btn wide-bt">Find Jobs</button>
</div>
</div><!--ui grid-->
</form>
</div><!--ui container-->
</div><!--m-banner-1-->
</div>
<br>
<br>
#endsection
I want when user clicks search button it should redirect to another page and display data got from Ajax call.
Also please suggest is this the correct way of achieving this using AngularJS.
I am new to AngularJs and Laravel.
There are multiple ways to achieve this.
1. Load data in a service. After get data from http
$scope.homepageSearch = function(search) {
homepagesearchService.getData(search).then(function(data) {
$scope.result = data;
DataService.set(data);
// and move to another page using $state.go('whatever page you want')
console.log(data);
});
}
//in that page load data from service
var data = DataService.get()// and here you can use that data
//in service
//make a var holdingdata; like
set(data){
holdingdata = data;
}
get(){
return holdingdata;
}
you can use localStorage after http success save data in local storage, and move to another page and get data from localStorage
you can also use $state service of angular like
$state.go('toState', { 'data':httpData});
and from that page get data from param using $stateParam service of anguar.
***From my point of view method 1 and 3 is good. you can use any of them.
I consider another page means ANOTHER VIEW OF ANGULAR APP:
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/router-url', {
controller: 'AnotherController',
templateUrl: 'Partials/ViewStart.html'
})
$scope.homepageSearch = function(search) {
homepagesearchService.getData(search).then(function(data) {
$scope.result = data;
console.log(data);
$location.path('/router-url/');
});
}

AngularJS Pass Database Data between Controllers

I am a little confused about how to pass my database data loaded in a controller to another controller.
I load some list items from the server and on each item click I want to open the details about that item on another screen according to its id.
I read some questions about making a service or use $rootScope but $rootScope should be avoid as much as possible.
What is the best way of doing this in my case and could you show me how to do it? Should I load the data inside a service or there is an easiest way in my case?
list item using 1st controller:
<div class="item item-body list-container" id="temporada2016-list-item-container4" ng-model="item_id" ng-repeat="x in items" item="x" href="#/x/{{x.ID}}" ng-click="open_item(x)" ng-show="news_list">
<div id="temporada2016-markdown7" style="margin-top:0px;color:#666666;">
<h2 style="color:#008BBB;">{{ x.TITLE }}</h2>
</div>
</div>
1st controller
.controller('temporada2016Ctrl', ['$scope', '$http', function ($scope, $http) {
$scope.active_news_btn = true;
$scope.search_news = true;
$scope.news_list = true;
$scope.albums_list = false;
$http.get("http://localhost/select-news.php").then(function(response){
console.log(response);
console.log(JSON.stringify(response));
$scope.items = response.data;
});
$scope.open_item = function(x){
//alert("Item id: " + x.ID);
$http.post("http://localhost/select-news-by-id.php", {'item_id': x.ID}).then(function(response){
console.log(response);
console.log(JSON.stringify(response));
$scope.all = response;
$scope.title = response.data[0].TITLE;
$scope.body = response.data[0].BODY;
});
}
}])
second screen (details) using 2nd controller where I want to load the same title and news body
<ion-view title="Detalhes" id="page4" style="background-color:#FFFFFF;">
<ion-content padding="true" class="has-header">
<h3 id="detalhes-heading1" style="color:#008BBB;font-weight:600;font-style:italic;">{{title}}</h3>
<div id="detalhes-markdown3" style="color:#000000;">
<p>{{body}}</p>
</div>
<form id="detalhes-form4" class="list">
<button id="detalhes-button6" style="color:#008BBB;text-align:left;border-radius:9px 9px 9px 9px;" class="button button-calm button-clear icon ion-ios-heart-outline like_btn"></button>
<label class="item item-input" id="detalhes-textarea1">
<span class="input-label"></span><textarea placeholder=""></textarea>
</label>
</form>
<button id="detalhes-button17" style="color:#FFFFFF;" class="button button-positive">Comment</button>
</ion-content>
</ion-view>
2nd controller
.controller('detalhesCtrl', ['$scope', '$stateParams', function ($scope, $stateParams) {
}])
PHP
<?php
include_once('conn.php');
$data = json_decode(file_get_contents("php://input"));
if(property_exists($data, 'item_id')){
$item_id = $data->item_id;
$sql = $mysqli->query("SELECT * FROM news WHERE id = '".$item_id."'");
if($sql->num_rows > 0){
while($row = $sql->fetch_array(MYSQLI_BOTH)){
$registro = array(
"ID" => $row['id'],
"TITLE" => $row['title'],
"BODY" => $row['body']
);
$retorno[] = $registro;
}
}
$mysqli->close();
$retorno = json_encode($retorno);
echo $retorno;
}
?>
In your app-config
$stateProvider
.state('master', {
url: '/master',
templateUrl: 'views/master.html',
controller: 'MasterCtrl',
data: {
someThingToPassToMasterState: false
}
})
.state('details', {
url: '/details',
data : {
somethingToPassToDetailsState: false
},
templateUrl: 'views/details.html',
controller: 'DetailsCtrl'
});
And then in your MasterCtrl
$scope.onClick = function(obj) {
var dataToPass = {};
dataToPass.obj = obj;
dataToPass.somethingElse = 'blah blah';
$state.go('details', {somethingToPassToDetailsState: dataToPass});
}
// Now in the DetailsCtrl
if(!$state.params.somethingToPassToDetailsState) {
// handle this
// maybe do a $state.go('default') and then return to end execution of this controller
}
// Some code
In master.html, using ng-repeat to simulate master-details page redirection
<div ng-repeat="o in objects">
<div ng-click="redirectTo(o)">{{o.name}}</div>
</div>
The idea is to pass day directly from one state to another on state transition. You can either pay in I'd and make api call AFTER transitioning to these new state or get the response from api and then paas required data to the next state
First of all, it is highly recommended you make your http calls in a factory or a service. This will make your code more reusable and it will look something like this:
app.factory("responseFactory", function($http) {
return {
getData: function() {
//Code for making http call goes in here
$http.get("http://localhost/select-news.php").then(function(response){
return(response.data);
});
},
postData: function(x) {
$http.post("http://localhost/select-news-by-id.php", {'item_id': x.ID})
.then(function(response){
return(response.data);
});
}
};
});
You could later use this to call in your controller by injecting this factory in your controller and calling this factory something like this:
app.controller('temporada2016Ctrl', ['$scope', 'responseFactory', function ($scope, responseFactory) {
$scope.items = responseFactory.getData();
$scope.opnItem = function(x){
$scope.all = responseFactory.postData(x);
$scope.title = all.TITLE;
$scope.body = all.BODY;
}
}]);
Now, to make the data available in your second controller, you could do a few things.
Pass it through the $rootScope, which as you already said, should be avoided as much as possible to not clutter the rootScope. It can have many consequences. - NOT RECOMMENDED
Make a service call from the second controller and you will have all the data you need from the api. However, if you edit the data in the first controller and wish to make edited data available in the second controller, that will not be possible using this method. Also, making http calls is costly and it highly recommended to minimize your number of http calls in the app. - NOT RECOMMENDED
Use Angular service/factory - HIGHLY RECOMMENDED
app.factory('commonData', function() {
var data;
return{
setData: setData,
getData: getData
};
//setter
function setData(dataToBeShared) {
data = dataToBeShared;
}
//getter
function getData() {
return data;
}
});
Now you can inject this factory into your controllers and use the setter and getter methods easily. DO not forget to inject the responseFactory which we created earlier!
After injecting it into your first controller, you can call the commonData factory and use the setter method to set the data, something like this:
app.controller('temporada2016Ctrl', ['$scope', 'responseFactory', 'commonData', function ($scope, responseFactory, commonData) {
//All your controller code, including calling the factory like I earlier explained...it all goes here
commonData.setData(passTheDataThatYouWantToShare);
}]);
Now, to get the data in the other controller, all you need to do is access the factory's getter method and you get the data! That will be something like this:
app.controller('detalhesCtrl', ['$scope', '$stateParams', 'commonData', function ($scope, $stateParams, commonData) {
$scope.commonData = commonData.getData();
//Use $scope.commonData to use all the data that has come in from first controller
}]);
Now, the data that is passed from controller 1 is stored in the factory and can be retrieved in the second controller whenever you want. Suppose you would like to display them as panes, next to each other, you might want to add watchers, otherwise this method should work fine for you.
NOTE: This can be achieved without using setter and getter methods, but using them is a good practice and is very useful when an app gets bigger.
Pass data through state params using Angular UI router. It seems to me that you are using Angular UI router which comes bundled with ionic. This can also be used when you are routing. At the time of writing this answer, another answer on this thread (by SLearner) has already explained this method and if it is recommended or not is more or less your choice depending on the level of functionality you want. However, in my opinion, I would not go in with this solution. You can find some more answers on this topic on this thread: AngularJS: Pass an object into a state using ui-router
So, concluding my answer, in my opinion, it is best you go in for an angular factory. IMHO, that is the best solution. Hope your queries are answered.
Cheers!
Share data between two controller is not good practice.
We need to put the data in service which can easily be shared with any number of controllers
Service: MyService
this.dbDataSearch = function(parameters){
// Search record from database
this.resultData = data;
}
In Convtoller 1:
$scope.data = MyService.resultData;
In Convtoller 2:
$scope.data = MyService.resultData;
....
In Convtoller n:
$scope.data = MyService.resultData;
Once service variable will update all these controller variables automatically updated.

Grab session variable from php page via jquery?

I edited my original text to demostrate my entire set of code for those that weren't understanding my question. All this works perfect when I had my database use MyISAM but when I changed over to InnoDB I now have to account for my foreign key or the mysql_queries won't successfully execute. I have the user_id in a session variable that gets created at the time a user logs in. I would figure I need to relay that number (int) from this session variable and append it to the $_GET so that it can be transferred to the todo.class.php for processing right?
the final get() would perhaps need to look like this ?action=new&user_id=1 (or what ever number the user is)&text=text type by user...
if there is a better way to do this, i'm all ears and ready to learn! ;-)
todo.js
$(document).ready(function(){
$(".todoList").sortable({
axis : 'y',
containment : 'window',
update : function(){
var arr = $(".todoList").sortable('toArray');
arr = $.map(arr,function(val,key){
return val.replace('todo-','');
});
$.get('././process/todo/todo.ajax.php',{action:'rearrange',positions:arr});
},
/* Opera fix: */
stop: function(e,ui) {
ui.item.css({'top':'0','left':'0'});
}
});
var currentTODO;
$("#dialog-confirm").dialog({
resizable: false,
height:130,
modal: true,
autoOpen:false,
buttons: {
'Delete item': function() {
$.get("././process/todo/todo.ajax.php",{"action":"delete","id":currentTODO.data('id')},function(msg){
currentTODO.fadeOut('fast');
})
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog('close');
}
}
});
$('.todo').live('dblclick',function(){
$(this).find('a.edit').click();
});
$('.todo a').live('click',function(e){
currentTODO = $(this).closest('.todo');
currentTODO.data('id',currentTODO.attr('id').replace('todo-',''));
e.preventDefault();
});
$('.todo a.delete').live('click',function(){
$("#dialog-confirm").dialog('open');
});
$('.todo a.edit').live('click',function(){
var container = currentTODO.find('.text');
if(!currentTODO.data('origText'))
{
currentTODO.data('origText',container.text());
}
else
{
return false;
}
$('<input type="text">').val(container.text()).appendTo(container.empty());
container.append(
'<div class="editTodo">'+
'<a class="saveChanges" href="#">Save</a> or <a class="discardChanges" href="#">Cancel</a>'+
'</div>'
);
});
$('.todo a.discardChanges').live('click',function(){
currentTODO.find('.text')
.text(currentTODO.data('origText'))
.end()
.removeData('origText');
});
$('.todo a.saveChanges').live('click',function(){
var text = currentTODO.find("input[type=text]").val();
$.get("././process/todo/todo.ajax.php",{'action':'edit','id':currentTODO.data('id'),'text':text});
currentTODO.removeData('origText')
.find(".text")
.text(text);
});
var timestamp=0;
$('#addButton-todo').click(function(e){
if((new Date()).getTime() - timestamp<5000) return false;
$.get("././process/todo/todo.ajax.php",{'action':'new','text':'New Todo Item. Doubleclick to Edit.','rand':Math.random()},function(msg){
$(msg).hide().appendTo('.todoList').fadeIn();
});
timestamp = (new Date()).getTime();
e.preventDefault();
});
});
todo.class.php
<?php
class ToDo{
private $data;
public function __construct($par){
if(is_array($par))
$this->data = $par;
}
public function __toString(){
return '
<li id="todo-' . $this->data['id'] . '" class="todo">
<div class="text">' . $this->data['text'] . '</div>
<div class="actions">
Edit
Delete
</div>
</li>';
}
public static function edit($id, $text){
$text = self::esc($text);
if(!$text) throw new Exception("Wrong update text!");
mysql_query("UPDATE `todo` SET `text` = '".$text."' WHERE `id`=".$id );
if(mysql_affected_rows($GLOBALS['link'])!=1)
throw new Exception("Couldn't update item!");
}
public static function delete($id){
mysql_query("DELETE FROM `todo` WHERE `id` = ".$id);
if(mysql_affected_rows($GLOBALS['link'])!=1)
throw new Exception("Couldn't delete item!");
}
public static function rearrange($key_value){
$updateVals = array();
foreach($key_value as $k=>$v)
{
$strVals[] = 'WHEN '.(int)$v.' THEN '.((int)$k+1).PHP_EOL;
}
if(!$strVals) throw new Exception("No data!");
mysql_query("UPDATE `todo` SET `position` = CASE `id`".join($strVals)." ELSE `position` END");
if(mysql_error($GLOBALS['link']))
throw new Exception("Error updating positions!");
}
public static function createNew($uid,$text){
$text = self::esc($text);
if(!$text) throw new Exception("Wrong input data!");
$posResult = mysql_query("SELECT MAX(`position`)+1 FROM `todo`");// WHERE `user_id` = 1");
if(mysql_num_rows($posResult))
list($position) = mysql_fetch_array($posResult);
if(!$position) $position = 1;
mysql_query("INSERT INTO `todo` SET /*`user_id` = {$uid},*/ `text` = '".$text."', `position` = ".$position);
if(mysql_affected_rows($GLOBALS['link'])!=1)
throw new Exception("Error inserting TODO!");
echo (new ToDo(array(
'id' => mysql_insert_id($GLOBALS['link']),
'text' => $text
)));
exit;
}
public static function esc($str){
if(ini_get('magic_quotes_gpc'))
$str = stripslashes($str);
return mysql_real_escape_string(strip_tags($str));
}
}
?>
todo.ajax.php
<?php
require "../../dbc.php";
require "../../resources/classes/todo.class.php";
$id = (int)$_GET['id'];
try{
switch($_GET['action'])
{
case 'delete':
ToDo::delete($id);
break;
case 'rearrange':
ToDo::rearrange($_GET['positions']);
break;
case 'edit':
ToDo::edit($id,$_GET['text']);
break;
case 'new':
ToDo::createNew($_GET['text']);
break;
}
}
catch(Exception $e){
echo $e->getMessage();
die("0");
}
echo "1";
?>
Why do you need the session id on the client side? jQuery is sending a GET request to a PHP script on your server. To your PHP script it looks like any other request. The $_SESSION array will be in place and all the session-related functions will work just fine.
Trusting the client to provide a session id is a really bad idea.
I don't follow your script entirely, but to my knowledge the only way to get the current session ID reliably into JavaScript space is
(... head section of the HTML document ...)
<script type="text/javascript">
php_session_id = "<?php echo session_id(); ?>"
alert("The PHP session ID is "+php_session_id);
</script>
#s2xi I realize you are looking for an answer to a simple question, "How do I get the PHP session id into my javascript?" and Unicron's answer is a foolproof way of doing that.
I think we are just trying to figure out why you need to put the PHP session id in your GET request. Your PHP script will always know the user's session id, you just need to call session_id(). There's no need to put it in your GET request. (Let's ignore the cookies-disabled edge case for now, I think it's clear we have bigger fish to fry)
Other things I'm worried about:
Tying data in your database to the session id doesn't make a whole lot of sense. As soon as that user's session expires, you will never be able to tie that data back to them. Am I missing something here?
You are using GET requests to perform actions and modify data. This is a really bad idea.

Categories