We are using CodeIgniter to wrap some internal functions and to display the results in json.
Occasionally our internal functions might have debug strings printed to the screen. So we have started using output buffering to capture any debug and add this to the result $data['response']['debug'] = $ob;
This seems to have worked pretty well as we have started dropping this code into most our publicly exposed CI functions.
We seem to be repeating this code flow a-lot now.
What would be the best way to extract the 'repeated' sections into a general template that is called when required? (not every function implements this - just most).
Example code:
public function some_function($var){
ob_start(); //repeated
$this->load->model('some_model');
$result = $this->some_model->do_something($var);
if($result){
$data['response']['result'] = true;
}else{
$data['response']['error'] = 'Something not found.';
}
$ob = ob_get_clean(); //repeated
if($ob!=''){
$data['response']['debug'] = $ob; //repeated
}
$this->load->view('json',$data); //repeated
}
If you have PHP 5.3.0 or higher, you can do something like this :
function debug_func($code){
ob_start(); //repeated
$code();
$ob = ob_get_clean(); //repeated
if($ob!=''){
$data['response']['debug'] = $ob; //repeated
}
$this->load->view('json',$data); //repeated
}
and use your code like this :
debug_func(function(){
$this->load->model('some_model');
$result = $this->some_model->do_something($var);
if($result){
$data['response']['result'] = true;
}else{
$data['response']['error'] = 'Something not found.';
}
});
and do all your codeing like that.
Ofcourse you can also wrap the repeated code in 2 functions and call them instead, just as annoying but will save you some space.
Related
So I have a case were I need to interpret a PHP file and then put it in a variable as a string.
I have this some what common helper function to do this:
function ob ($path) {
ob_start();
include($path);
$string = ob_get_contents();
ob_end_clean();
return $string;
}
Just give it the path and it will give you the string after it has been interpreted. Works great.
However I also need to send it a variable. I tried just appending a GET request string to the path, but it appeared not to work. The function prototype would look like this:
// how would I implement this?
function ob ($path, $variable_to_send) {
}
How should I do this?
Simply use a global variable.
Set it in one file like this:
$GLOBALS['arg'] = 'test';
Access it in another file similarly:
$arg_passed = $GLOBALS['arg'];
If you wanted to architect this a bit more use the registry pattern.
Note this assumes that this is the same HTTP request. If you need persistence across HTTP requests use session variables.
Let the external script is external.php:
<?php
echo $argument;
?>
and the caller scrip is caller.php (on the same folder of external.php):
<?php
function ob ($path, $argument) {
ob_start();
include($path);
$string = ob_get_contents();
ob_end_clean();
return $string;
}
$out = ob("external.php","Ciao");
echo "$out Cade";
?>
The result will be:
Ciao Cade
I'm new to PHP and I have an issue I can't seem to fix or find a solution to.
I'm trying to create a helper function that will return an 'object' filled with information pulled from an XML file. This helper function, named functions.php contains a getter method which returns a 'class' object filled with data from an SVN log.xml file.
Whenever I try to import this file using include 'functions.php'; none of the code after that line runs the calling function's page is blank.
What am I doing wrong?
Here is what the functions.php helper method and class declaration looks like:
<?php
$list_xml=simplexml_load_file("svn_list.xml");
$log_xml=simplexml_load_file("svn_log.xml");
class Entry{
var $revision;
var $date;
}
function getEntry($date){
$ret = new Entry;
foreach ($log_xml->logentry as $logentry){
if ($logentry->date == $date){
$ret->date = $logentry->date;
$ret->author = $logentry->author;
}
}
return $ret;
}
I'm not sure what the point of having a separate helper function from the class is, personally I'd combine the two. Something like this
other-file.php
require './Entry.php';
$oLogEntry = Entry::create($date, 'svn_log.xml');
echo $oLogEntry->date;
echo $oLogEntry->revision;
Entry.php
class Entry
{
public $revision;
public $date;
public $author;
public static function create($date, $file) {
$ret = new Entry;
$xml = simplexml_load_file($file);
foreach($xml->logentry as $logentry) {
if($logentry->date == $date) {
$ret->date = $logentry->date;
$ret->author = $logentry->author;
$ret->revision = $logentry->revision;
}
}
return $ret;
}
}
EDIT
In light of the fact OP is new to PHP, I'll revise my suggestion completely. How about ditching the class altogether here? There's hardly any reason to use a class I can see at this point; let's take a look at using an array instead.
I might still move the simplexml_load_file into the helper function though. Would need to see other operations to merit keeping it broken out.
entry-helper.php
function getEntry($date, $file) {
$log_xml = simplexml_load_file($file);
$entry = array();
foreach($log_xml->logentry as $logentry) {
if($logentry->date == $date) {
$entry['date'] = $logentry->date;
$entry['author'] = $logentry->author;
$entry['revision'] = $logentry->revision;
}
}
return $entry;
}
other-file.php
require './entry.php';
$aLogEntry = Entry::create($date, 'svn_log.xml');
echo $aLogEntry['date'];
echo $aLogEntry['revision'];
EDIT
One final thought.. Since you're seemingly searching for a point of interest in the log, then copying out portions of that node, why not just search for the match and return that node? Here's what I mean (a return of false indicates there was no log from that date)
function getEntry($date, $file) {
$log_xml = simplexml_load_file($file);
foreach($log_xml->logentry as $logentry) {
if($logentry->date == $date) {
return $logentry;
return false;
}
Also, what happens if you have multiple log entries from the same date? This will only return a single entry for a given date.
I would suggest using XPATH. There you can throw a single, concise XPATH expression at this log XML and get back an array of objects for all the entries from a given date. What you're working on is a good starting point, but once you have the basics, I'd move to XPATH for a clean final solution.
Here's the code for my original PHP code:
public function outputText() {
$i = 1;
foreach($this->sorted_data as $this->data) {
echo "$i. ".$this->data[0]."<br/>";
$i++;
}
}
And here's the code for the PHPUnit:
public function testVerify() {
$yn = new SortThisData();
$yn->readFile("input.txt");
$output = $yn->outputText();
$this->assertTrue(is_string($output));
//if(!is_string($yn->get()))
// return false;
//$this->assertNotEmpty($yn->get());
}
The class is called SortThisData in the original PHP file.
When I used gettype(), it said it was null. I'm trying to verify that it is a string so it can pass in PHPUnit. Is there a way I can do this?
You're looking for assertInternalType().
Update: I didn't realize you were echoing the output. You will probably need to use output buffering to capture the text.
public function testVerify() {
$yn = new SortThisData();
$yn->readFile("input.txt");
// start output buffering and capture the output
ob_start();
$yn->outputText();
$output = ob_get_clean();
$this->assertInternalType('string', $output);
}
No disagreement with Baylor's answer. To answer the question, as asked, what you had was also good enough:
$this->assertTrue(is_string($output));
Or you could have done:
$this->assertEquals('string',gettype($output));
(The advantage of the latter is, when it fails, it will also tell you the type of $output; assertTrue will only tell you that something failed.)
assertInternalType() does exactly that, but was only introduced in PHPUnit 3.5, and you will still find PHPUnit 3.4 in use on some machines.
Ok folks,
I have an odd issue with a function of mine.
public function getOutages($Site)
{
// pull a json data dump of all outages
If(!$Site){
echo '[{}]';
}else{
$this->load->database('default', TRUE);
$this->db->where('Clear', '0');
$this->db->where('FracID', $Site);
$query = $this->db->get('vw_Outages');
echo json_encode($query->result_array());
}
}
This when accesed directly will not echo anything. By enabling the profiler though it functions fine and outputs the data.
public function getOutages($Site)
{
$this->output->enable_profiler(TRUE);
// pull a json data dump of all outages
If(!$Site){
echo '[{}]';
}else{
$this->load->database('default', TRUE);
$this->db->where('Clear', '0');
$this->db->where('FracID', $Site);
$query = $this->db->get('vw_Outages');
echo json_encode($query->result_array());
}
}
Any insight into this would be more then welcome :D .
CodeIgniter has an output buffering system (which also allows it to do things like cache controller output, set headers, and collect view output). You don't usually echo from a controller method. Do this instead:
public function mymethod() {
$anobject = array();
$output = json_encode($anobject);
$this->output->set_content_type('application/json');
$this->output->set_output($output);
}
See the CodeIgniter documentation for the Output class.
Maybe you have output buffering or compression enabled-this could cause problems like this. Also check that the variable you're trying to output isn't empty. If this doesn't help, try using a view to display data.
Is it possible to have return statements inside an included file that is inside a function in PHP?
I am looking to do this as I have lots of functions in separate files and they all have a large chunk of shared code at the top.
As in
function sync() {
include_once file.php;
echo "Test";
}
file.php:
...
return "Something";
At the moment the return something appears to break out of the include_once and not the sync function, is it possible for the included file's return to break out?
Sorry for the slightly odly worked question, hope I made it make sense.
Thanks,
You can return data from included file into calling file via return statement.
include.php
return array("code" => "007", "name => "James Bond");
file.php
$result = include_once "include.php";
var_dump("result);
But you cannot call return $something; and have it as return statement within calling script. return works only within current scope.
EDIT:
I am looking to do this as I have lots
of functions in separate files and
they all have a large chunk of shared
code at the top.
In this case why don't you put this "shared code" into separate functions instead -- that will do the job nicely as one of the purposes of having functions is to reuse your code in different places without writing it again.
return will not work, but you can use the output buffer if you are trying to echo some stuff in your include file and return it somewhere else;
function sync() {
ob_start();
include "file.php";
$output = ob_get_clean();
// now what ever you echoed in the file.php is inside the output variable
return $output;
}
I don't think it works like that. The include does not simply put the code in place, it also evaluates it. So the return means that your 'include' function call will return the value.
see also the part in the manual about this:
Handling Returns: It is possible to
execute a return() statement inside an
included file in order to terminate
processing in that file and return to
the script which called it.
The return statement returns the included file, and does not insert a "return" statement.
The manual has an example (example #5) that shows what 'return' does:
Simplified example:
return.php
<?php
$var = 'PHP';
return $var;
?>
testreturns.php
<?php
$foo = include 'return.php';
echo $foo; // prints 'PHP'
?>
I think you're expecting return to behave more like an exception than a return statement. Take the following code for example:
return.php:
return true;
?>
exception.php:
<?php
throw new exception();
?>
When you execute the following code:
<?php
function testReturn() {
echo 'Executing testReturn()...';
include_once('return.php');
echo 'testReturn() executed normally.';
}
function testException() {
echo 'Executing testException()...';
include_once('exception.php');
echo 'testException() executed normally.';
}
testReturn();
echo "\n\n";
try {
testException();
}
catch (exception $e) {}
?>
...you get the following output as a result:
Executing testReturn()...testReturn() executed normally.
Executing testException()...
If you do use the exception method, make sure to put your function call in a try...catch block - having exceptions flying all over the place is bad for business.
Rock'n'roll like this :
index.php
function foo() {
return (include 'bar.php');
}
print_r(foo());
bar.php
echo "I will call the police";
return array('WAWAWA', 'BABABA');
output
I will call the police
Array
(
[0] => WAWAWA
[1] => BABABA
)
just show me how
like this :
return (include 'bar.php');
Have a good day !