XML parse with PHP - php

i have little problem with XML. My XML file is look like this:
http://pastebin.com/MQUB2W2B i user pastebin because this site don't support xml code.. ://
so i need to select source mount "/stream" and other source mount "/". And my PHP code look like this:
Class stream {
Public Function __construct($host, $path, $user, $pass, $mpoint){
$this->host = $host;
$this->path = $path;
$this->user = $user;
$this->password = $pass;
$this->mpoint = $mpoint;
$this->url = "http://{$this->user}:{$this->password}#{$this->host}/{$this->path}";
$this->xml = simplexml_load_file($this->url);
}
Public Function audio($url, $format){
return print "<audio controls> <source src=\"{$url}\" type=\"audio/{$format}\"> </audio>";
}
Public Function stream_meta(){
$xml = $this->xml->registerXPathNamespace('test', '/{$this->mpoint}');
$result = $xml->xpath('test:artist');
return $result;
}
Public Function nowplay(){
return $this->xml->source[0]->artist;
}
Public Function download($format){
$link = "http://{$this->host}/{$this->mpoint}";
if($format == "m3u"){
return "{$link}.m3u";
}
elseif($format == "xspf"){
return "{$link}.xspf";
}
elseif($format == "vclt"){
return "{$link}.vclt";
}
return false;
}
}
So now i asking what i do wrong or what i can do better? i need to select artist data and know what is the source mount "?what is this?". I really need help. I don't know what i can do and i don't invent other way to do this. I am so tired and i am really need help! Please, can anyone help me? I don't want to use "nowplay()" function. because source mount "/example" change sometimes...

I'm not entirely clear on what you are trying to achieve, but here is a basic example of getting the mount and artist of each source in the XML:
function sources(){
foreach($this->xml->source as $source) {
echo "Mount: " . $source->attributes()['mount'] . '<br>';
echo "Artist: " . $source->artist . '<br>';
}
}
Or to find the artist for a source:
$source = $this->find_source('/stream');
$artist = $source->artist;
function find_source($s){
foreach($this->xml->source as $source) {
if ($source->attributes()['mount'] == $s) {
return $source;
}
}
}
Alternatively, you could do the same with XPath without needing to use a loop. For example:
function find_source($s){
return $this->xml->xpath('/icestats/source[#mount="'.$s.'"]')[0];
}

Related

Redirecting users to a 404 page by using pretty urls

I'm working on a mvc project just for fun.
Pretty urls already work, but i can't find a good way with my code to send visitors to a 404 page, in case the page doesn't exist which people are looking for.
class Route
{
private $_uri = array();
private $_method = array();
/*
* Builds a collection of internal URL's to look for
* #param type $uri
*/
public function add($uri, $method = null)
{
$this->_uri[] = '/' . trim($uri, '/');
if($method != null){
$this->_method[] = $method;
}
}
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
foreach($this->_uri as $key => $value){
if(preg_match("#^$value$#",$uriGetParam)){
if(is_string($this->_method[$key])){
$useMethod = $this->_method[$key];
new $useMethod();
}
else{
call_user_func($this->_method[$key]);
}
}
}
}
}
I didn't analyze your code thoroughly (I couldn't, not sure what is the example route / method you're adding with ->add), but the solution seems simple to me:
public function submit()
{
$uriGetParam = isset($_GET['uri']) ? '/' . $_GET['uri'] : '/';
$routeFound = false;
foreach($this->_uri as $key => $value){
if(preg_match("#^$value$#",$uriGetParam)){
if(is_string($this->_method[$key])){
$routeFound = true;
$useMethod = $this->_method[$key];
new $useMethod();
}
else{
$routeFound = true;
call_user_func($this->_method[$key]);
}
}
}
if(!$routeFound){
http_response_code(404);
echo 'ooooh, not found';
//or:
include('404.php');
die();
}
}
p.s. http_response_code is a built-in function:
https://secure.php.net/manual/en/function.http-response-code.php
edit: you could put the code starting with 'http_response_code(404);' to a separate function and just call it.

How to properly rewrite php code from version 5.6 to 7.x?

I tied it myself but it does not work for me. How to properly change for example this old code to be compatible with php 7.x?
class DbSimple_Generic
{
function& connect($dsn)
{
// Load database driver and create its instance.
$parsed = DbSimple_Generic::parseDSN($dsn);
if (!$parsed) {
$dummy = null;
return $dummy;
}
$class = 'DbSimple_'.ucfirst($parsed['scheme']);
if (!class_exists($class)) {
$file = str_replace('_', '/', $class) . ".php";
if ($f = #fopen($file, "r", true)) {
fclose($f);
require_once($file);
} else {
$base = basename($file);
$dir = dirname(__FILE__);
if (#is_file($path = "$dir/$base")) {
require_once($path);
} else {
trigger_error("Error loading database driver: no file $file in include_path; no file $base in $dir", E_USER_ERROR);
return null;
}
}
}
$object =& new $class($parsed);
if (isset($parsed['ident_prefix'])) {
$object->setIdentPrefix($parsed['ident_prefix']);
}
class DbSimple_Mysql_Blob extends DbSimple_Generic_Blob
{
var $blobdata = null;
var $curSeek = 0;
function DbSimple_Mysql_Blob(&$database, $blobdata=null)
{
$this->blobdata = $blobdata;
$this->curSeek = 0;
}
function read($len)
{
$p = $this->curSeek;
$this->curSeek = min($this->curSeek + $len, strlen($this->blobdata));
return substr($this->blobdata, $this->curSeek, $len);
}
function write($data)
{
$this->blobdata .= $data;
}
function close()
{
return $this->blobdata;
}
function length()
{
return strlen($this->blobdata);
}
}
function& _performNewBlob($blobid=null)
{
$obj =& new DbSimple_Mysql_Blob($this, $blobid);
return $obj;
}
I tried to use every possible way to make this work like this:
$object = new $class($parsed);
$object->method();
Becase it seems for PHP 7.x is this the most problematic part:
$object =& new $class($parsed);
But thisdid not work. I tried to find it on some PHP documentation but no luck so far. So how to properly rewrite this? Thank you
Using this on Ubuntu Server 64bit 16.04+ with Apache and mysql.
Probably it is a better idea to understand that function and rewrite in a cleaner way but please find below my changes, hopefully it helps.
class DbSimple_Generic
{
function connect($dsn)
{
// Load database driver and create its instance.
$parsed = DbSimple_Generic::parseDSN($dsn);
if (!$parsed) {
$dummy = null;
return $dummy;
}
$class = 'DbSimple_'.ucfirst($parsed['scheme']);
if (!class_exists($class)) {
$file = str_replace('_', '/', $class) . ".php";
if ($f = #fopen($file, "r", true)) {
fclose($f);
require_once($file);
} else {
$base = basename($file);
$dir = dirname(__FILE__);
if (#is_file($path = "$dir/$base")) {
require_once($path);
} else {
trigger_error("Error loading database driver: no file $file in include_path; no file $base in $dir", E_USER_ERROR);
return null;
}
}
}
$object = new $class($parsed);
if (isset($parsed['ident_prefix'])) {
$object->setIdentPrefix($parsed['ident_prefix']);
}
}
public static function parseDSN($dsn){ // public or private depends on what you intend to do
// implementation here...
}
public function setIdentPrefix($identPrefix){
// implementation here...
}
}
class DbSimple_Mysql_Blob extends DbSimple_Generic_Blob
{
var $blobdata = null;
var $curSeek = 0;
function __construct($blobdata=null) // use __construct for class constructor
{
$this->blobdata = $blobdata;
$this->curSeek = 0;
}
function read($len)
{
$p = $this->curSeek;
$this->curSeek = min($this->curSeek + $len, strlen($this->blobdata));
return substr($this->blobdata, $this->curSeek, $len);
}
function write($data)
{
$this->blobdata .= $data;
}
function close()
{
return $this->blobdata;
}
function length()
{
return strlen($this->blobdata);
}
}
function _performNewBlob($blobid=null)
{
$obj = new DbSimple_Mysql_Blob($blobid); // no need to use &
return $obj;
}
Just don't ever use =& operator. It's been useless since PHP 5.0 and removed in PHP 7.0:
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.new-by-ref
You will find more things on that page that no longer work in PHP 7.

global file_get_contents variable outside of function possible?

I have a json api I'm trying to feed to several functions. I'm not entirely sure how to make the file_get_contents global so that it can be accessed by multiple functions at once.
Here is my current PHP code:
function getVideoTitle($getVideoID) {
$json_output = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=".$getVideoID."&key={MY_KEY}&fields=items(id,snippet(title,description),statistics)&part=snippet,statistics");
$json = json_decode($json_output, true);
$video_title = $json['items'][0]['snippet']['title']; // Video Title
return $video_title;
}
function getVideoDesc($getVideoID) {
$json_output = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=".$getVideoID."&key={MY_KEY}&fields=items(id,snippet(title,description),statistics)&part=snippet,statistics");
$json = json_decode($json_output, true);
$video_description = $json['items'][0]['snippet']['description']; //Description
return $video_description;
}
echo getVideoTitle($getVideoID);
echo getVideoDesc($getVideoID);
If I remove the two $json variables and place them outside of the function I get an error that it couldn't find the variable $json.
Also, would making it a global variable make it run faster? Retrieving the API is currently running pretty slowly. Would it be wiser to switch to Javascript..? Thanks.
If the $json is supposed to be constant, then I believe you're better to create a class, since you need to provide the $getVideoID for the ID of the video, and additionally you have the ability to change the video conveniently :)
<?php
class MyVideoClass {
private $json = null;
public function __construct($videoID) {
$this->changeVideo($videoID);
}
public function changeVideo($videoID) {
$json_output = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=".$videoID."&key={MY_KEY}&fields=items(id,snippet(title,description),statistics)&part=snippet,statistics");
$this->json = json_decode($json_output, true);
}
function getVideoTitle() {
$video_title = $this->json['items'][0]['snippet']['title']; // Video Title
return $video_title;
}
function getVideoDesc() {
$video_description = $this->json['items'][0]['snippet']['description']; //Description
return $video_description;
}
}
// somewhere:
$myVideo = new MyVideoClass($yourVideoID);
echo $myVideo->getVideoTitle();
echo $myVideo->getVideoDesc();
// sometime else
$myVideo->changeVideo($anotherVideoID);
echo $myVideo->getVideoTitle();
echo $myVideo->getVideoDesc();
here what i have wrote for you
<?php
class Video{
private $data;
public function __construct($videoId, $key){
$json_output = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=".$videoId."&key=".$key."&fields=items(id,snippet(title,description),statistics)&part=snippet,statistics");
isset($json_output) ? $this->data = $json_output : $this->data = false;
}
public function getTitle(){
if($this->data){
$video_title = $this->data['items'][0]['snippet']['title']; // Video Description
return $video_title;
}else{
return false;
}
}
public function getDesc(){
if($this->data){
$video_desc = $this->data['items'][0]['snippet']['description']; // Video Title
return $video_desc;
}else{
return false;
}
}
public function change($videoId, $key){
$this->__construct($videoId, $key);
}
}
Usage Example:
include('video.php'); // if you going to save the class in separate file
$video = new Video('Video-Id-Here', 'your-key');
echo $video->getTitle().'<br/>';
echo $video->getDesc();
//new video
$video->change('new-video-id', 'new-key');
echo $video->getTitle().'<br/>';
echo $video->getDesc();
and you can add more functions to the class

PDO request within a class

Here is my class :
class ProfileLink {
function profileLink(PDO $pdo, $string, $i=0)
{
if ($i!=0) {
$link = $string . '-' . $i;
} else {
$link = $string;
}
$req = $pdo->prepare('SELECT link FROM users WHERE link = ?');
$req->execute(array($link));
$nb = $req->rowCount();
$req->closeCursor();
if ($nb > 0) {
$i++;
return profileLink($pdo, $string, $i);
} else {
return $link;
}
}
}
When I call the profileLink function from the class, it doesn't work, but if I call it outside the class, everything is ok. It might be a problem with the PDO, what do you think ?
require_once ('lib/profileLink.class.php');
$profileLink = new ProfileLink();
$link = $profileLink->profileLink($pdo, $string);
I would store the instance of PDO as a class property so that it can be easily accessed within the class. Note that my example uses slightly different syntax (modern PHP).
class ProfileLink {
protected $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function profileLink($string, $i=0)
{
if ($i!=0) {
$link = $string . '-' . $i;
} else {
$link = $string;
}
$req = $this->pdo->prepare('SELECT link FROM users WHERE link = ?');
$req->execute(array($link));
$nb = $req->rowCount();
$req->closeCursor();
if ($nb > 0) {
$i++;
return profileLink($string, $i);
} else {
return $link;
}
}
}
$profileLink = new ProfileLink($pdo);
2 Things:
here
return profileLink($pdo, $string, $i);
you are missing a $this, because it's no regular function but a class method:
return $this->profileLink($pdo, $string, $i);
And second, your method has the same name as the class (except of the first capital letter), and thus seems to be interpreted as constructor. I have just tested this:
class Test {
function test() {
echo "test";
}
}
$t = new Test();
And it outputs "test".
So you should rename your method to getLink or something similar.

PHP using functions in classes

Class to display different views for my blog.
class SB_Display {
public function __contruct() {
include_once('settings/db.settings.php');
$mysqli = new mysqli($SB_dbsettings['host'],$SB_dbsettings['user'],$SB_dbsettings['pass'],$SB_dbsettings['dbname']);
}
private function List_Display() {
$VIEW = '';
include_once('views/list.html.view.php');
$sql = "SELECT * FROM sb_posts ORDER BY ID DESC LIMIT '$SETTINGS->maxposts'";
$sql = $mysqli->real_escape_string($sql);
$res = $mysqli->mysqli_query($sql);
if($res->numrows > 0) {
$res->data_seek(0);
while ($row = $res->fetch_assoc()) {
foreach($row as $key => $value) {
$BLOG->$key = $value;
$VIEW .= $HTML;
}
}
} else {
$VIEW .= 'No Posts To Display';
}
return $VIEW;
}
private function Single_Display($id) {
$VIEW = '';
include_once('views/single.html.view.php');
$sql = "SELECT * FROM sb_posts WHERE BID = '$id'";
$sql = $mysqli->real_escape_string($sql);
$res = $mysqli->mysqli_query($sql);
$row = $res->fetch_assoc();
foreach($row as $key => $value) {
$BLOG->$key = $value;
}
$VIEW .= $HTML;
return $VIEW;
}
private function Create_Display() {
include_once('views/create.html.view.php');
return $HTML;
}
private function Edit_Display($id) {
$VIEW = '';
$sql = "SELECT * FROM sb_posts WHERE BID = '$id'";
$sql = $mysqli->real_escape_string($sql);
$res = $mysqli->mysqli_query($sql);
$row = $res->fetch_assoc();
foreach($row as $key => $value) {
$BLOG->$key = $value;
}
$BLOG->id = $id;
$VIEW .= $HTML;
return $VIEW;
}
public function SB_Get_Display($type,$id) {
switch($type) {
case 'list':
$this->content = List_Display();
return $this;
break;
case 'single':
$this->content = Single_Display($id);
return $this;
break;
case 'create':
$this->content = Create_Display();
return $this;
break;
case 'edit':
$this->content = Edit_display($id);
return $this;
break;
}
}
}
When using this class in the following manner ..
$BODY = new SB_Display();
$BODY->SB_Get_Display('list','');
I get this error:
Fatal error: Call to undefined function List_Display()
I can't figure out why. Any help would be greatly appreciated.
You need to use $this->function() instead of function() to call a method.
On a side-note, your constructor function name is incorrect. It's __contruct() but needs to be __construct() to be used as a constructor. Besides that, your indentation is horrible and makes the code hard to read.
I agree with #Corbin, that's a very bad idea. Also, personally, I love the autoload classes approach.
Some might say it's sloppy and the easy way out, but it forces you to really think about your classnames and directories, plus you avoid problems when you're renaming files/ classes. In your case you'd have to search for all files trying to include it and rename everything manually.
"my" approach: create a inc.php or something in the root of your site, and put this in it:
PHP
//autoload classes
function __autoload($class_name){
set_include_path(get_include_path().PATH_SEPARATOR.'/usr/share/file/'); //also
//include magic file location
// put the path to your class files here
$path = $_SERVER['DOCUMENT_ROOT'].'/lib/classes/';
// tell PHP to scan the default include path AND your include path
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
// name your classes and filenames with underscores, i.e., Net_Whois stored in
//Net_Whois.php
$classfile = str_replace("_", DIRECTORY_SEPARATOR, $class_name) . ".php";
require_once($classfile);
}
just initialise your db connections in the inc.php file as well and you can access them pretty much anywhere.
now just include the inc.php file in every new class you create, and you never have to look back again( depending on the project ofcourse)

Categories