Searched stackoverflow for this and found no answer
Coming from Ruby On Rails and Rspec, I need a tool like rspec (easier transition). Installed it through PEAR and tried to run it but it's not working (yet)
Just wanna ask around if anyone's using it have the same problem, since it's not running at all
tried running it with an example from the manual - http://dev.phpspec.org/manual/en/before.writing.code.specify.its.required.behaviour.html
phpspec NewFileSystemLoggerSpec
returns nothing
even running
phpspec some_dummy_value
returns nothing
Development on PHPSpec has restarted since August 2010, after a 2 years break. The code base looks more stable now. I would give another try.
The website is now located at www.phpspec.net
You can find the documentation at http://www.phpspec.net/documentation. It is basically an update of the first version.
Should you require any further assistance you can also reach the developers through their mailing list:
http://groups.google.com/group/phpspec-dev
I also couldn't get it to run, but you can also use BDD with PHPUnit. Check the documentation:
Was really looking forward to using PHPSpec, oh I guess will check into PHPUnit
I tried using phpspec but found it too buggy/immature. I can highly recommend SimpleTest for writing unittests.
You can write RSpec-ish types of tests in PHPUnit, but it's hindered by a couple of things.
PHPUnit mocks don't let you
re-declare them so it's hard to set
up a bunch of stubs in a before
method and then override them as
needed. You can work around this by
arranging for the stubs to be setup
after the expectations, but it's odd.
PHP isn't as dynamic as Ruby so you
can't easily mock or stub out class
methods unless you specifically
design the class for this and even
then it's pretty ugly. (This may
change with PHP 5.3's late static
binding features).
I have used PHPSpec succesfully but it's not actively developed now is it? It's great but don't think I would go with a stalled project. Anyway to the point I used the following setup to run the tests from the webbrowser, maybe you'll find something to help you to set it up for CLI.
PHPSpecConfiguration.php
$projectDir = realpath( dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' ) . DIRECTORY_SEPARATOR;
$simdal_root = $projectDir . 'library';
$phpspec_root = $projectDir . '..' . DIRECTORY_SEPARATOR . 'PHPSpec';
$mockery_root = $projectDir . '..' . DIRECTORY_SEPARATOR . 'Mockery';
$paths = array(
'SimDAL'=>$simdal_root,
'PHPSpec'=>$phpspec_root,
'Mockery'=>$mockery_root
);
set_include_path( implode( PATH_SEPARATOR, $paths ) . PATH_SEPARATOR . get_include_path() );
require_once 'PHPSpec.php';
require_once 'Mockery/Framework.php';
class Custom_Autoload
{
public static function autoload($class)
{
//$path = dirname(dirname(__FILE__));
//include $path . '/' . str_replace('_', '/', $class) . '.php';
if (preg_match('/^([^ _]*)?(_[^ _]*)*$/', $class, $matches)) {
include str_replace('_', '/', $class) . '.php';
return true;
}
return false;
}
}
spl_autoload_register(array('Custom_Autoload', 'autoload'));
and then the file that runs it all: AllSpecs.php;
require_once 'PHPSpecTestConfiguration.php';
$options = new stdClass();
$options->recursive = true;
$options->specdocs = true;
$options->reporter = 'html';
PHPSpec_Runner::run($options);
I don't like CLI testing...But this might help someone.
Hello its pretty old Q. in deed, but i think http://behat.org/ should be here. Everyone has this problem should check it out.
Note that PHPSpec is discontinued:
http://blog.astrumfutura.com/2010/05/the-mockery-php-mock-objects-made-simple/#comment-88628508
Related
I'm building a fork of OpenCart that involves some very heavy rewriting of the core functionality to including dedicated themes that allow for overriding the core, similar to the Wordpress theme system.
If a given controller, model or language file exists in the theme, use that, if not, use the core file.
I'm currently autoloading all the system files which works great. But I'm wondering if it would be better to also autoload all my controller, model, and language files as well?
I've noticed that (even in OpenCart) the same file gets searched via the file system, and loaded multiple times. (models and languages in particular)
Would it not be more efficient to autoload all these files then simply instantiate the exiting class, over searching for the files each time then using an include?
Let me give an example ...
My homepage contains the following modules:
Slideshow,
Latest Products,
Featured Products,
Carousel
This along with the header and footer controllers ends up calling:
$this->load->model('catalog/product');
23 times.
That's 23 times that the same exact file is being searched for using the file system. Plus of course all the other models being called.
So I guess the question is really more about overhead ...
Is it more expensive to autoload (and cache) all files regardless of whether they're being called, or search the file system and do includes for each file as it's needed?
I'm sure this is an age old question but I've yet to see a definitive answer.
And BTW either answer is fine, I'd just like to be as efficient as possible in my code.
Well I get Your point but to be honest You should be concerned about this only in the case You can prove that the response times are somehow slower because of this reason. After having such proof (which is relative to the server's hardware, connection speed, whether it is sunny or stormy weather or day or night) You can issue a bug and a patch-fix using the github repository.
Now the model loading performs file_exists check, then include_once and afterwards it instantiates a new model object while setting (or replacing) it as some key in the registry. Current code looks like this (system/engine/loader.php):
public function model($model) {
$file = DIR_APPLICATION . 'model/' . $model . '.php';
$class = 'Model' . preg_replace('/[^a-zA-Z0-9]/', '', $model);
if (file_exists($file)) {
include_once($file);
$this->registry->set('model_' . str_replace('/', '_', $model), new $class($this->registry));
} else {
trigger_error('Error: Could not load model ' . $model . '!');
exit();
}
}
By just slight modification we can improve this code to perform only one file_exists check, only one include_once and having only one model's object:
public function model($model) {
$key = 'model_' . str_replace('/', '_', $model);
if (!$this->registry->has($key)) {
$file = DIR_APPLICATION . 'model/' . $model . '.php';
$class = 'Model' . preg_replace('/[^a-zA-Z0-9]/', '', $model);
if (file_exists($file)) {
include_once($file);
$this->registry->set($key, new $class($this->registry));
} else {
trigger_error('Error: Could not load model ' . $model . '!');
exit();
}
}
}
You can now put some time debugging into the original code and to the fixed one and find out whether this brings so great improvement :-)
Edit: Either way I would check how is this handled and done in OpenCart 2.0 (in it's latest status since it is not release-ready so far) and file an issue only if this is done the same way. Otherwise just fix your own installation(s)...
I'd like to use Cakephp classes (models) from regular php code unrelated to cakephp.
I tried this but it didn't work:
include('/lib/Cake/Core/App.php');
App::uses('Business', 'Model');
$b = new Business();
The last line gives me an error, and I've also tried several workarounds with no success...
I'll be ever grateful for a good answer :)
EDIT: Here's the solution I found! (Thanks, #Burzum!):
I copied webroot/index.php to webroot/cake_setup.php and removed the last few lines so it will only include stuff and not actually execute anything:
App::uses('Dispatcher', 'Routing');
$Dispatcher = new Dispatcher();
$Dispatcher->dispatch(
new CakeRequest(),
new CakeResponse()
);
Then, this worked from external php code:
if (!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
include_once(__DIR__ . DS . '..' . DS . 'v2' . DS . 'app' . DS . 'webroot' . DS . 'cake_setup.php');
App::uses('AppModel', 'Model');
App::uses('Business', 'Model');
$b = new Business();
Thanks a lot guys!
CakePHP is not made to be used piece by piece. If you're looking for a standalone ORM go for doctrine or propel.
You can keep trying it but you'll have to run the bootstrapping process of the framework (see what it does inside webroot/index.php) and register it's class loader and point it the the core include path.
Edit:
While looking at this again today, I think the proper solution here would be to expose the stuff your need from your CakePHP app through an API that the other non-Cake app can consume. REST is pretty easy with CakePHP you might want to look at that solution. You don't tight couple your other app on the CakePHP app then. You can even upgrade to 3.0 without having to touch the other non-Cake app then.
So I'm currently picking up Unit testing and on my travels I've discovered I also might need to mock the file system as well as database queries and the like.
I've read a recommendation from the PHPUnit documentation that vfsStream is a good library for mocking the file system.
I'm having issues with using it, though.
I don't really understand how to set it up despite following documentation provided in the wiki hosted on GitHub.
I've abstracted file system interaction into it's own class with some aptly named methods. That doesn't appear to be the issue at hand, as when I wasn't mocking the file system it worked as intended.
Here is how I setup the test:
public function setUp()
{
// Setup here
$this->filesystem = new Filesystem;
vfsStreamWrapper::register();
$this->root = vfsStream::setup('test-dir');
}
Here is an example test I written to test for the creation of a directory:
public function testCanCreateDirectory()
{
$dir = vfsStream::url($this->root->path() . '/sub-dir');
$filesystem = $this->filesystem;
$filesystem->makeDirectory($dir);
$this->assertTrue($filesystem->isDirectory($dir));
}
That appears to work, so far so good. However, this next test fails:
public function testCanPutFile()
{
$file = $this->root->url() . '/sub-dir/test.txt';
$contents = "test text";
$filesystem = $this->filesystem;
$filesystem->put($file, $contents);
$this->assertTrue($filesystem->isFile($file));
$this->assertEquals($contents, $filesystem->get($file));
}
As far as I can tell from the documentation this should work, but obviously my reading of it isn't correct and I've gone awry somewhere along the lines.
Any hints as to how I can resolve this issue, as I've been changing lines over and over and cannot figure it out for the life of me.
Thank you in advance!
I appear to have solved this. The manner of the fix is... somewhat unsatisfactory, maybe someone could help explain the reasoning behind this I'd be happy.
public function testCanPutFile()
{
$dir = vfsStream::url($this->root->path()) . '/sub-dir';
$file = $dir . '/test.txt';
$contents = "test text";
$filesystem = $this->filesystem;
$this->assertTrue($filesystem->makeDirectory($dir));
$this->assertTrue($filesystem->isDirectory($dir));
$filesystem->put($file, $contents);
$this->assertTrue($filesystem->isFile($file));
$this->assertEquals($contents, $filesystem->get($file));
}
Is how I fixed the issue. It appears I have to recreate the structure per test method. I don't really understand why I have to do it this way. Maybe I'm missing something here but I can't see what I'm doing wrong and there are a paltry number of decent examples on the internet, with most of them found on the authors GitHub wiki. I do believe I've probably misread the documentation though, so a correction on this issue would also be much appreciated.
I am seeking a way of allowing my PHP applications to be perfectly portable. My problem is, although I am utilizing relative path to include PHP classes, I always face issues when I try to deploy me application in a new environment.
For example, I have implemented an application under Ubuntu and it just run perfectly. However, when I moved it to a shared hosting running Centos, I had to modify all the include statements.
So, I am asking about the best way to include classes, considering having multiple folders which contain various classes that are dependent on another multiple classes in different levels of the folder hierarchy.
just keep one "main" folder.
In your index.php (for ex.) configure the "main" folder location and either use that as the 'base' for includes (I suppose you hard-code the include/require path?)
Else use the 'base' within the autoload functionality.
Now you are able to move the 'main' folder around and all you need to do is update just one line of code in your index.php
It is still a manual update. True that. You can also ofc. use something like glob() and search for you "mainlib.php" file (for ex.) and 'cache' that folders location to use it in the next calls?
This for example is how I do it:
<?php
/**
* cfg.php
*
* Main config file
*
* #package Public
*/
// Compatibility
$version = '5.2.3';//restricted by htmlentities()' 4th parameter
if(version_compare(PHP_VERSION, $version, '<')) {
die('Required PHP version is ' . $version . ', current is ' . PHP_VERSION);
}
// Environment
define('DEVELOPMENT', in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1')));
define('PRIVATE_DIR', DEVELOPMENT ? 'private' . DIRECTORY_SEPARATOR : '..'.DIRECTORY_SEPARATOR.'private_html'.DIRECTORY_SEPARATOR.'tickets');
define('APPLICATION_LINK','application_red'.DIRECTORY_SEPARATOR);
define('LIBRARY_LINK','library'.DIRECTORY_SEPARATOR);
define("MEM_START",memory_get_usage(true));
// Behavior
if(DEVELOPMENT) {
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);//report all errors
}
else {
ini_set('display_errors', 'Off');
error_reporting(0);
}
// Timezone
date_default_timezone_set('Europe/Amsterdam');
// Constants
define('ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
define('APP', ROOT . '..'.DIRECTORY_SEPARATOR.PRIVATE_DIR.''.APPLICATION_LINK);
define('LIB', ROOT . '..'.DIRECTORY_SEPARATOR.PRIVATE_DIR.''.LIBRARY_LINK);
define('CACHE', APP.'cache'.DIRECTORY_SEPARATOR);
index.php/utest.php:
<?php
include("cfg.php");
// Start library
require_once LIB.'Library.php';
$library = new Library();
//etc.......
You don't need to make reference to a hardwired folder at all. In my current project I do this:
public static function getProjectRoot()
{
return realpath(
dirname( __FILE__ ) . DIRECTORY_SEPARATOR . '..' .
DIRECTORY_SEPARATOR . '..'
);
}
The class in which this features is two folder levels inside the project - hence the two .. operators to traverse up the directory structure. Since that location will never change in relation to the project root, this doesn't need changing, and I don't ever need to hardwire any paths.
Edit: in relation to include/require statements, use an autoloader, and (apart from a couple of bootstrap files) you don't generally need to use includes/requires at all.
Ok I think I am pushing my self to far here, I'm createing a project in my own MVC even I don't know what MVS is itself,
<?php
class init
{
function __construct()
{
$this->enviroment();
$this->start();
}
function enviroment()
{
/* Required Classes */
require_once( ROOTPATH . BOOTSTRAP . REDENGINE . '/class.debug.php');
require_once( ROOTPATH . BOOTSTRAP . REDENGINE . '/class.theme.php');
require_once( ROOTPATH . BOOTSTRAP . REDENGINE . '/class.url.php');
require_once( ROOTPATH . BOOTSTRAP . REDENGINE . '/language/class.lang.php');
require_once( ROOTPATH . BOOTSTRAP . REDENGINE . '/class.sessions.php');
}
function start()
{
/* Start Classes */
$uSys = new Urlsystem;
$fragments = $uSys->getFragments();
$tSys = new ThemeSystem;
$lSys = new LanguageSystem;
$sSys = new Sessions;
/* defineing APPVIEWS & APPCONTROLLER */
define( 'APPVIEWS', '/appviews' );
define( 'APPCONTROLLER', '/appcontroller' );
if ( empty($fragments) )
{
require_once( ROOTPATH . APPCONTROLLER . '/app.home.php'); /* default app controller page */
require_once( ROOTPATH . APPVIEWS . '/view.home.php'); /* default app views page */
}
if ( !empty($fragments) )
{
// Start ENGINE
if ( !file_exists(ROOTPATH . APPCONTROLLER . '/app' . $fragments . '.php') &&
!file_exists(ROOTPATH . APPVIEWS . '/view' . $fragments. '.php')
) {
if ( file_exists(ROOTPATH . APPCONTROLLER . '/app.404.php') &&
file_exists(ROOTPATH . APPVIEWS . '/view.404.php')
) {
require ROOTPATH . APPCONTROLLER . '/app.404.php';
require ROOTPATH . APPVIEWS . '/view.404.php';
}
else {
echo "NO 404 APP || VIEW";
}
}
if ( file_exists(ROOTPATH . APPCONTROLLER . '/app' . $fragments . '.php') )
{
require ROOTPATH . APPCONTROLLER . '/app' . $fragments . '.php'; // load application
if ( file_exists(ROOTPATH . APPVIEWS . '/view' . $fragments . '.php') ) {
require ROOTPATH . APPVIEWS . '/view' . $fragments . '.php';// load view
}
}
// End ENGINE
}
}
} ?>
Ok, as you see my front controller, so I know it's failing, I just notice my fail after I nearly finish my project, especialy when I need to do www.someurl.com/?$getuser or www.someurl.com/myname or a user.
Anyway my question is when do we really need MVC for PHP?
I'm looking at facebook, etc
They still use the ?this=blabla get so they are not MVC , is that right? Anyway I'm still confused how facebook does www.facebook.com/myname without it. ( htaccess ? )
If they don't use MVC then when do we really need it?
Note :
I've read many thread about when use MVC, but I haven't found one in my problem, if there is please leave a comment so I can read :)
Thanks a lot.
I believe you are confused between MVC and having RESTful URL scheme (http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services).
MVC is just a coding pattern that separates entities and modules. Like Application Logic from GUI Templates while The URL pattern is a different thing altogether. URLs are just to access a Web Resource. MVC frameworks like CodeIgnitor can still give you 'ugly' URLs if you do not work it out with .htaccess
MVC is an architectural pattern focused on separation of concerns; the URL's have nothing to do with it.
URL's are handled by the server. If it's Apache you are using, set up mod_rewrite.
That being said, you might want not to reinvent the wheel, but look at options available out there, there are plenty of MVC-oriented PHP frameworks. Find one that you like and can be productive in and use it.
I think you're confusing MVC with query params. The two are not necessarily linked, though it is true that the more popular PHP MVC frameworks do mask the params by using mod_rewrite or an equivalent method.
MVC is simply a way to keep your presentation logic separate from your business logic. Think of it this way: if you have a site using MVC, you can easily create a mobile phone version by simply changing the views based on the browser, your site's logic doesn't need to change, just the HTML that is sent to the client.
It seems that your question is confusing two different topics together. Model View Controller(MVC) and pretty URLs.
Model View Controller is a design paradigm which allows you to separate your logic(model), your templates(views), and your directing input/output(controller).
Pretty URLs on the other hand, allow for redirecting urls based on format rules(typically .htaccess rules).
Model-View-Controller - design paradigm information.
Pretty URLs tutorial - implementation of using Apache's mod_rewrite.
mod_rewrite - information on what a rewrite engine is.
Saving your code, HTML, and data in different folders is the most basic way of structuring your application - and that's the primary reason for implementing MVC: organization.
The other design patterns present in most frameworks supplement MVC, and they promote code reuse, rapid development, etc. But you can do the latter even without MVC - all it takes is a code library! Most frameworks utilize the MVC design pattern, but MVC != frameworks.
Some frameworks require you to tweak Apache (Lighty, Nginx, etc) to make it a framework extension. Pretty URLs are just a way of presenting input data (view) that are consumed by the controller so the latter can route to the appropriate handler. Seen in this light, .htaccess is an integral part of MVC for such frameworks.
Before you plunge deeper into your project, it helps to do a little more research. Most frameworks have taken the convoluted approach to MVC, which have led many to confusion. Fat-Free Framework uses a more direct and easier-to-follow path.
you might consider starting by using one of the many different MVC frameworks out there, such as CodeIgniter or cakePHP. These frameworks have bene developed by many pople and refined over a period of time. MVC is not necessary, but once the boilerplate is established, creating web applications is very fast.
When to use... All the time, is a good practice.
Personally, my choice: Symphone and Doctrine can easier to write big applications by team. But began with CodeIgniter.
You are really making it hard on yourself by attempting to writing your own mvc. (You are not doing it by manipulating the URL scheme). While it is a good educational experience to write one yourself, you will not get the level of quality and the benefits of the MVC pattern by reinventing the wheel.
Write your app in symfony, zend, codeigniter cake or any of the good open source MVC frameworks out there. When you get a feel for how it should work, then you should create your own for fun.
These frameworks exist to make your projects faster to code and more maintainable.