I'm used to web development using LAMP, PHP5, MySQL plus NetBeans with Xdebug.
Now I want to improve my development, by learning how to use (A) proper testing and (B) a framework. So I have set up CodeIgniter, SimpleTest and the easy Xdebug add-in for Firefox. This is great fun because maroonbytes provided me with clear instructions and a configured setup ready for download. I am standing on the shoulders of giants, and very grateful.
I've used SimpleTest a bit in the past. Here is a the kind of thing I wrote:
<?php
require_once('../simpletest/unit_tester.php');
require_once('../simpletest/reporter.php');
class TestOfMysqlTransaction extends UnitTestCase {
function testDB_ViewTable() {
$this->assertEqual(1,1); // a pseudo-test
}
}
$test = new TestOfMysqlTransaction();
$test->run(new HtmlReporter())
?>
So I hope I know what a test looks like. What I can't figure out is where and how to put a test in my new setup. I don't see any sample tests in the maroonbytes package, and Google so far has led me to posts that assume unit testing is already functionally available. What do I do?
Edit:
If you are following the maroonbytes setup, just follow the instructions:
Download the SimpleTest framework and extract the files into your #codeigniter directory.
In both your main folder and your admin/application folder create a new folder called tests.
Within the new tests folder setup additional folders called ‘models’, ‘views’, ‘controllers’, ‘libraries’ and ‘helpers’.
Any file ending in .php and with a UnitTestCase inside any of those folders, should be run. :)
First, tests must be named properly. To test a controller welcome placed in the file welcome.php a test is named welcome_controller_test.php and stored under tests/controllers/. For more, see this post.
Second, Xdebug's GET argument interferes with the test routine. See post just above, also this post.
Third, the stub test I posted needed two four lines deleted:
//require_once('../simpletest/unit_tester.php');
//require_once('../simpletest/reporter.php');
...
//$test = new TestOfMysqlTransaction();
//$test->run(new HtmlReporter())
I am making tests fairly happily now. CodeIgniter lets me create/maintain tests easily, so my goal of TDD looks reachable. My earlier attempts at TDD gave me the idea, but scratch PHP was just too barren for me to be effective (and we won't discuss VBA!).
Related
I'm writing an C++ extension (dynamic load) for HHVM. I followed the instructions on this page:
https://github.com/facebook/hhvm/wiki/Extension-API
which links to an example in:
https://github.com/hhvm/extension-example
I compiled hhvm on Ubuntu 14.04 which took nearly 2 hours. Then I also compiled the example extension.
My question is, how to load it?
The information on the internet seems to be out-of-date or inconsistent.
Anyway, I first tried to create /etc/hhvm/config.hdf with these lines:
DynamicExtensions {
example = /path/to/example.so
}
Nothing happened. And then I saw this:
From: http:// hhvm.com/blog/4349/hhvm-3-0-0
We are moving from .hdf config files to .ini. The default one lives in
/etc/hhvm/php.ini. We don’t support all the old options yet, so you
can still use config.hdf for now, but be ready for it to die in the
next release. All of your favorite options will go from Foo { BarBaz =
True } to hhvm.foo.bar_baz = true.
OK, then I tried to put lines in /etc/hhvm/php.ini or /etc/hhvm/server.ini instead of .hdf
hhvm.dynamic_extensions.example = /path/to/example.so
But with no luck, nothing worked. I need more info/docs.
So, is there anyone know what happen? or if the HHVM team from Facebook see this post, could you please help me?
I see that you've managed to get it to load, so I'll just focus on not being able to find the function.
Shortly after the release of HHVM 3.0, the way that PHP files are loaded from extensions changed. Basically, the first four characters of the name of the file are stripped when embedding it, since it's expected to be ext_name.php. The example extension hadn't been updated for this change until last night.
The change is rather simple. Just rename example.php to ext_example.php and, in config.cmake change HHVM_SYSTEMLIB(example example.php) to HHVM_SYSTEMLIB(example ext_example.php) then re-run cmake . && make.
You can see the committed change (which does exactly this) here
I'm working on a Symfony 2 project running on a shared hosting (cheap but slow, I've to admit). Performances are really bad, even minifying all css/js and enabling the gzip compression (PHP output only with a custom php.ini). Server responds in 5-10 seconds, that is the time to parse and execute PHP files. Dowloading resources takes just millisecs, hence the delay is between the request and response. This is what (I think) I've found with the Chrome network console.
Looking at the annotation reader cache folder (app/cache/prod/annotations) I've noticed that and there are 441 *.cache.php files in it. I think that the annotations reader is going to read all of these files on each request!
This could be the source of the bad performances. How can I speed up things and write a custom annotation cache driver that uses just less files or a single file as annotations cache?
Merging annotation cache files into one won't speed up things, moreover, it
will slow them down. I've got an explanation for this statement.
First of all if you check the Annotation cache (file)reader source
82: public function getClassAnnotations(\ReflectionClass $class) {
....
$path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
if (!is_file($path)) {
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
....
return $this->loadedAnnotations[$key] = include $path;
So, basically, what happens here is that every file is annotation
content of specific class. It's a simple small file being fetched and
ready for use. If it's not there, cache is being 'slowly' generated manually
and getting saved for future use.
If you want this driver dump cache into one file, then instead of:
include $path;
you'll have to do something like:
file_get_contents('one_big_cache');
...searching/regexps/arrays/loops...
return $result;
And this looks way slower if you ask me.
I'm not claiming to be absolutely right on this one and will be glad to hear
opinions on this topic
I am using wampserver to test & run wordpress code in my local computer. In order to run pthread, I have followed the following steps:
1) I got the pthread zip file from http://windows.php.net/downloads/pecl/releases/pthreads/0.44/
(My machine has php 5.3.13 and downloaded the php_pthreads-0.44-5.3-ts-vc9-x86.zip file from the above link).
2) Extracted the zip file. Moved the php_pthreads.dll to the C:\wamp\bin\php\php5.3.13\ext directory.
3) Moved pthreadVC2.dll to the C:\wamp\bin\php\php5.3.13 directory.
4) Then Opened C:\wamp\bin\php\php5.3.13\php.ini and added the code extension=php_pthreads.dll at the begining of the file.
But when I try to run the following code:
<?php
class My extends Thread {
public function run() {
printf("%s is Thread #%lu\n", __CLASS__, $this->getThreadId());
}
}
$my = new My();
$my->start();
?>
It gives me the following error:
Fatal error: Class 'Thread' not found in C:\wamp\www\wp-admin\includes\post.php on line 2
Can you please tell me how to install pthreads in my computer to use with php? and do I have to install any other software?
I've noticed that wampserver has php.ini in two separate places. One place is in the /wamp/bin/php/php5... directory, and the other place is in the /wamp/bin/apache/apache.../bin directory (where "..." represents version numbers). The two files need to be identical, because apparently both are loaded at different times by the overall wampserver boot-up procedure.
(Note I only discovered this recently, and may be well "behind the curve" of doing fancy things with wampserver --maybe everyone else has been dealing with both files for a long time. So I don't know if this simple thing will fix your problem; I came here looking for info, myself, regarding doing some multi-threading stuff. :)
One other thing. According to this page: www.php.net/manual/en/pthreads.requirements.php
PHP has to be compiled with "--enable-zts" in order for pthreads stuff to work. I have not been able to find any evidence that the PHP part of wampserver was compiled that way.
(months later)
Having decided I didn't really immediately need to do any threading stuff, I went on to do other things, until the need actually arose. I now can say that the version of PHP compiled into WampServer does support the "pthread" extension, although some set-up work is needed, first. The instructions I saw mentioned putting a couple of .dll files (after a download and unZip) into certain places, but that didn't work for me. Copying them to the \Windows\System32 directory did work. (Putting them into the \apache...\bin directory also works; there are some other php .dll files in there.)
After that, much like what you did, it is necessary to define a "class" that extends the "Thread" class, in order to actually do something in another thread. The "run()" function in the Thread class is "abstract", and needs to be "realized" as an actual function in the extended class. Then the "new" operator can create an "instance", an object of that specified class, for actual use. Here's the class that I needed:
//Purpose: Use another thread to run the code in another php file, after a delay
class xT extends Thread
{ var $fil, $tim;
function savWhatWhen($f="", $t=0)
{ $this->fil = $f; //save What, file to process
$this->tim = $t; //save When, delay before processing file
return;
}
function run()
{ ini_set('max_execution_time', 600); //600 seconds = 10 minutes
sleep($this->tim); //do a delay; beware of max-exec-time!
include($this->fil); //load file-to-process, and process it
return;
} }
That "savWhatWhen()" function was created specifically for this extension of the basic Thread class. Here's some code for using that class:
$TH = new xT(); //prepare a separate Thread
$TH->savWhatWhen("d:/wamp/myscripts/test.php", 45);//file-name and delay time
$TH->start(); //after delay, process file
//the code that does this can terminate, while OTHER thread is doing a delay
Note for anyone copying this code, you might need to make sure your "open_basedir" setting in the php.ini allows access to the specified file.
More months later: With lots of things being worked on, I haven't put a lot of time into using my pthread object. I did encounter a peculiarity that makes me wonder about whether or not I can actually use pthreads the way I had hoped. Here is what I have observed:
1. An initial php file is called by AJAX, to do something.
2. The PHP processor on the Web Server does that thing.
3. Various data is supposed to be echoed to the browser.
4. The initial php file calls for the creation of another thread, and terminates.
5. The browser does not yet receive the echoed data!
6. The PHP processor on the Web Server does the work delegated to the second thread.
7. When the second thread terminates, NOW the browser receives the echoed data!
At this writing I'm thinking I missed something. Perhaps I need to do some forceful "flush" stuff when the first thread ends, so that the browser can receive the echoed data and the user can do things while the PHP processor on the server is also doing things.
Check for extension_dir = "ext" in you php.ini file. Make sure it points to the folder where your extensions reside and make sure it's not commented (it has a semicolon ; in front of it)
You have to add a require_once() with the path of the Thread class before extending it (if your framework don't use an autoload class system)
I've encountered the same problem, in my case placing the pthreadVC2.dll in
..wamp\bin\apache\Apache2.4.4\bin
(instead of ..\wamp\bin\php\php5.4.16 as the guide in php.net instructs) solved the problem
Wamp server has a separate php.ini config file for the browser and for the cli.
To use the pthreads module in the browser with WAMP Server you need to copy the "pthreadVC2.dll" into the apache "bin" directory also.
You should now have he "pthreadVC2.dll" in both of these folders (if installed in default location):
C:\wamp\bin\php\php[x.x.xx]\bin
C:\wamp\bin\apache\apache[x.x.x]\bin
You will also need to update the php.ini file within the php bin directory AND the apache bin directory to include:
extension=php_pthreads.dll
This now means you can use pthreads in the browser and in the cli with wamp server
After encountering the same problem, I noticed that I have installed the wrong Pthread version (3.1.6 : requires PHP7+) which wasn't compatible with my PHP version (5.5.12). Solved the problem with Pthread version 0.0.44. An earlier version should probably work well.
Here is the download page for Pthread and the installation page. Be careful about the both php.ini location as mentioned above (Apache folder=for Browser, PHP folder=CLI).
I am trying to run a unit test that checks if the assets are properly installed.
I simply make a request to an existing file and check if there is no errors:
$client = static::createClient();
$client->request('GET', '/bundles/mybundle/css/bg.css');
$this->assertFalse($client->getResponse()->isNotFound(), "Assets seem to not be installed");
Unfortunately, after checking with the Response instance, it always tries to reach some kind of controller with a route:
No route found for "GET /bundles/mybundle/css/bg.css"
Is there a way to make a pure request here without going through the routing system?
You'd need to use an actual HTTP client (the client implementation you are using for functional testing doesn't actually make HTTP requests) to make that request, but you seem to be approaching this the wrong way. Installing assets should be part of your post deployment scripts -- thus the test would always (or sometimes depending on the configuration of your development box, but the point is that it's a deployment/staging detail) fail anyway. Just do a simple test in your deployment process in any language you want to make sure that the assets installed correctly.
Simplified example
<?php
system('git clone myrepo');
echo 'Pulled codebase';
system('composer install'); // install dependencies
echo 'Dependencies installed';
system('php app/console assets:install web --symlink'); // install assets
echo 'Assets installed -- testing for presence';
if( !file_exists('blah.gif') ) {
echo 'assets not installed! error!';
}
The test client doesn't actually hit your web server, it simulates a request directly through your application.
Therefore it could never be used to check if an asset exists within your file structure. It could be used for dynamically loaded assets, but that's not the case here nor is it usually a case.
As #Lusitanian suggested, you can use standard file functions PHP has to offer to check if it exists.
If you need help locating the path of these assets, check out the Kernel::locateResource() method:
$this->container->get('kernel')->locateResource('#AcmeDemoBundle/Resources/public/css/main.css');
This will throw an exception if the resource was not found.
I've recently started using APC cache on our servers. One of the most important parts of our product is a CLI (Cron/scheduled) process, whose performance is critical. Typically the batchjob consists of running some 16-32 processes in parallel for about an hour (they "restart" every few minutes).
By default, using APC cache in CLI is a waste of time due to the opcode cache not being retained between individual calls. But APC also contains apc_bin_dumpfile() and apc_load_dumpfile() functions.
I was thinking these two function might be used to make APC efficient in CLI mode by having it all compiled sometime outside the batchjob, stored in a single dumpfile and having the individual processes load the dumpfile.
Does anybody have any experience with such a scenario or can you give good reasons why it will or will not work? If any significant gains could reasonably be had, either in memory use or performance? What pitfalls are lurking in the shadows?
Disclaimer: As awesome as APC is when it works in CLI, and it is awesome, it can equally be as frustrating. Use with a healthy load of patience, be thorough, step away from the problem if you're spinning, keep in mind you are working with cache that is why it seems like its doing nothing, it is actually doing nothing. Delete dump file, start with just the basics, if that doesn't work forget it try a new machine, new OS, if it is working make a copy, piece by piece expand functionality - there are loads of things that won't work, if it is working commit or make a copy, add another piece and test again, for sanity-check recheck the copies that were working before, cliches or not; if at first you don't succeed try try again, you can't keep doing the same thing expecting new results.
Ready? This is what you've been waiting for:
Enable apc for cli
apc.enable-cli=1
it is not ideal to create, populate and destroy the APC cache on every CLI request
- previous answer by unknown poster since removed.
You're absolutely right that sucks, lets fix it shall we?
If you try and use APC under CLI and it is not enabled you will get warnings.
something like:
PHP Warning: apc_bin_loadfile(): APC is not enabled,
apc_bin_loadfile not available.
PHP Warning: apc_bin_dumpfile(): APC is not enabled,
apc_bin_dumpfile not available.
Warning: I suggest you don't enable cli in php.ini, it is not worth the frustration, you are going to forget you did it and have numerous other headaches with other scripts, trust me its not worth it, use a launcher script instead. (see below)
apc_loadfile and apc_dumpfile in cli
As per the comment by mightye php we need to disable apc.stat or you will get a warnings
something like:
PHP Warning: apc_bin_dumpfile(): Excluding some files from apc_bin_dump[file].
Cached files must be included using full path with apc.stat=0.
launcher script - php-apc.sh
We will use this script to launch our apc enabled scripts (ex. ./php-apc.sh apc-cli.php) instead of changing the properties in php.ini directly.
#/bin/sh
php -d apc.enable_cli=1 -d apc.stat=0 $1
Ready for the basic functionality? Sure you are =)
basic APC persisted - apc-cli.php
<?php
/** check if dump file exists, you don't want to use file_exists */
if (false !== $dump_file = stream_resolve_include_path('apc.dump'))
/** so where were we lets have a look see shall we */
if (false !== apc_bin_loadfile($dump_file))
/** fetch what was stored last run just for fun */
if (false !== $value = apc_fetch('my.awesome.apc.store'))
echo "$value from apc\n";
/** store what gets fetched the next run just for fun */
apc_store('my.awesome.apc.store', 'awesome in cli');
/** what a shlep lets not do that all over again shall we */
apc_bin_dumpfile(array(),null,'apc.dump');
Notice: Why not use file_exists? Because file_exists == stat you see and we want to reap the reward that is apc.stat=0 so; work within the include path; use absolute and not relative paths - as returned by stream_resolve_include_path(); avoid include_once, require_once use the non *_once counterparts; check your stat usage, when not using APC(Muchos important senor), with the help of a StreamWrapper echo for calls to method url_stat; Oops: Fatal scope over-run error! aborting notice thread. see url_stat
message: Error caused by StreamWrapper outside the scope of this discussion.
The smoke test
Using the launcher execute the basic script
./php-apc.sh apc-cli.php
A whole bunch of nothing happened that's what we want right, why else do you want to use cache? If it did output anything then it didn't work, sorry.
There should be a dump file called apc.dump see if you can find it? If you can't find it then it didn't work, sorry.
Good we have the dump file there were no errors lets run it again.
./php-apc.sh apc-cli.php
What you want to see:
awesome in cli from apc
Success! =)
There are few in PHP as satisfying as a working APC implementation.
nJoy!
I would definitely not use it in the CLI as when you restart it, it's almost as if it was never running in the first place!
The better way of using APC is to have it running on the webserver itself all the time, this way with it being active it will actually do what it's supposed to do!
I tryed with curl and APC.it works
use these commands in CLI
curl --data "param1=value2" http://testsite.com/test.php
so it will post data to test.php and you writes the code in it.