Interface '...' not found in (PHP SQL Query Builder) - php

I'm trying to use PHP SQL Query Builder in a project I'm working on. I am installing it manually. I did this by copying the src directory into my project and then using the following code within my class:
$this->builder = new NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder();
The error I get whenever the builder is used is:
[18-Apr-2017 12:57:48 UTC] PHP Fatal error: Interface 'NilPortugues\Sql\QueryBuilder\Builder\BuilderInterface' not found in /home/thomassm/public_html/php/lib/sqlbuilder/Builder/GenericBuilder.php on line 24
GenericBuilder.php
namespace NilPortugues\Sql\QueryBuilder\Builder;
use NilPortugues\Sql\QueryBuilder\Builder\Syntax\WriterFactory;
use NilPortugues\Sql\QueryBuilder\Manipulation\AbstractBaseQuery;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryInterface;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryFactory;
use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
use NilPortugues\Sql\QueryBuilder\Syntax\Column;
use NilPortugues\Sql\QueryBuilder\Syntax\Table;
/**
* Class Generic.
*/
class GenericBuilder implements BuilderInterface
{//...}
BuilderInterface.php
namespace NilPortugues\Sql\QueryBuilder\Builder;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryInterface;
/**
* Interface BuilderInterface.
*/
interface BuilderInterface
{
/**
* #param QueryInterface $query
*
* #return string
*/
public function write(QueryInterface $query);
/**
* #param QueryInterface $query
*
* #return string
*/
public function writeFormatted(QueryInterface $query);
}
I assume the error is somehow caused by the way the files are called, any suggestions?

I am installing it manually. I did this by copying the src directory into my project and then using the following code within my class: ...
Every source file should be included through include/requrie before using. But PHP allow to setup autoloading for classes, interfaces and traits. In short, when runtime meets an undefined class then a special callback invokes, which can load the relevant file.
Although formally the autoloading rules can be arbitrary, but most of the modern projects supports the common community standard: PSR-4 Autoloader. So, you need an implementation of this standard.
As said in the library description, the recommended way to install is through Composer:
php composer.phar require nilportugues/sql-query-builder
Composer provides own PSR-4 implementation and generates file vendor/autoload.php. Usually this file included at the application entry point. It allow using the classes from all required libraries.
You can use the packages without the Composer (relevant answer). But it requires a lot of work (you still need an PSR-4 autoloader) and this way is rarely used today.

Related

PHPDocumenter No summary for class

I am using PHPDocuementer and I keep getting these messages for my classes:
Parsing /code/vendor/prodigyview/helium/app.class.php
No summary for class \prodigyview\helium\He2App
But when code is the following:
<?php
/**
* The main application for instantiaing the He2MVC Framework and bringing together the parts required for the system to work.
*
* The application is what is called with Helium is first initiliaed in the frontend controller. It will autoload the components,
* set the registry and then send the application into the router. The boostrap of the framework should be called sometime during
* this point.
*
* #package prodigyview\helium
*/
namespace prodigyview\helium;
class He2App extends \PVStaticInstance {
}
Am I missing something?
The one docblock you have should be moved down to just above the class line. Its current location is being interpreted as the file-level docblock rather than a class-level docblock.
After doing this, you might start seeing warnings about file-level docblock missing. Just add a new docblock at the same place you have the current example one. You could use an exact copy of the one you already have up there, since its content seems to fit for the file as well as the class.

Codeception DataFactory interaction between helper and other factories

I'm looking into using DataFactory's in Codeception for seeding of data, and for use in our acceptance tests. In the documentation there's mention of 2 approaches, one using the helper file and one using factories files.
We load both options using this snippet from our acceptance.suite.yml
class_name: AcceptanceTester
modules:
enabled:
- Db
- WebDriver
- \Helper\Acceptance
- Doctrine2:
connection_callback: getEntityManager
- DataFactory:
factories: tests/_support/factories
depends: Doctrine2
- \Helper\Factory
Both of the options seem to load correctly. As per the documentation I can then define factories like this, which will allow interaction with Doctrine.
// tests/_support/Helper/Factory.php
class Factory extends Module
{
/**
* #param array $settings
* #throws \League\FactoryMuffin\Exceptions\DefinitionAlreadyDefinedException
* #throws \Codeception\Exception\ModuleException
*/
public function _beforeSuite($settings = [])
{
/** #var Module\DataFactory $factory */
$factory = $this->getModule('DataFactory');
/** #var EntityManager $em */
$em = $this->getModule('Doctrine2')->_getEntityManager();
$factory->_define(User::class,[
// generate random user name
'name' => Faker::name(),
]);
parent::_beforeSuite($settings);
}
}
As per the other option, I can also create factories by loading all files from within tests/_support/factories, such as below:
// tests/_support/factories/seed.php
use League\FactoryMuffin\Faker\Faker;
/** #var \League\FactoryMuffin\FactoryMuffin $fm */
$user = $fm->create(User::class);
dd($user);
However, the seed.php version cannot seem to share the Factory, and errors with:
The model definition 'User' is undefined.
I wondered if maybe this could be solved by moving the Factory.php logic into the initialize() method but this seems to be called before FactoryMuffin has been initiliazed.
The documentation for this with codeception seems a bit sparse, and the FactoryMuffin docs, while better, don't cover Codeception integration. Just trying to work out if i'm missing something, or I just need to repeat the code in each place if I want to use both files/methods.
This is an old question and technology moves fast so the documentation has likely changed since this was originally asked but I'll make an attempt in case anyone else stumbles across it like I did.
You're using the DataFactory module which is great as it comes with the integration for Codeception out of the box. The two methods you've described are actually ways of integrating DataFactory with your data. By creating factory files, you've given DataFactory a means of generating data. But what if you have some data already in the database that you'd like to use in your tests as well? That's where you would use the Helper class. According to the DataFactory Module docs:
In cases you want to use data from database inside your factory definitions you can define them in Helper. For instance, if you use Doctrine, this allows you to access EntityManager inside a definition.
As for your issue of seed.php not finding the User model, you need to specify it according to the definition given in your factory. For example, if your factory file looks similar to this
<?php
use League\FactoryMuffin\Faker\Facade as Faker;
$fm->define('app\models\User')->setDefinitions([
'name' => Faker::name(),
... // the rest of your properties here
]);
Then seed.php would look like
// tests/_support/factories/seed.php
use League\FactoryMuffin\Faker\Faker;
$user = $fm->create('app\models\User');
Once you have the DataFactory module installed and configured, you can simply call it within the appropriate testing suite via have, haveMultiple, or make. See the Codeception Docs

Codeception autoloading classes

I'm having issues using the Codeception autoloader to load some abstract test classes. The reason for the abstract class is to mimic the structure of classes that are used in the application to cut down on the amount of code needed to test the application thoroughly.
Lets say I have an abstract class for testing, let say "AbstractRepositoryTester" which is only used in the "repositories" test suite (I like to separate things out for organisational purposes).
Each and every repository that I test that implements a "RepositoryContract" will have a test that also extends the "AbstractRepositoryTester" with some overridden abstract methods.
Now when doing this, the abstract class won't be loaded during testing and has to be loaded manually in a bootstrap file. There is also another abstraction that extends the vanilla Codeception test class so that I can set a few variables (namely for laracasts/testdummy).
Both classes will fail to load with out manual entry in to the _boostrap file. To add to this, the suite specific bootstrap file fails to load files or seemingly execute at all so I am forced to place all bootstrap code for all suites in to the global _bootstrap file.
I also attempted to use Codeceptions autoloading class \Codeception\Util\Autoload:: with the "load" method but it doesn't seem to work.
Right now I'm using require_once in the global _bootstrap so finally to the question:
Is there a correct way of autoloading (or just loading) a class to be used as part of a test both globally and per suite?
Am I on the right track overall in abstracting my tests like this? TDD is new to me and I am trying to better my development workflow (with help from Laracasts).
I've searched every where for an answer to load the classes I need but usually all I'll find is PHPUnit specific answers which don't appear to work. I have also peered through the Codeception documentation which feels a bit sparse on the subject and the API docs don't explain the method call usage in the case of Autoload::load
Cheers,
- Everon.
You can do this for your whole test suit, or just individual components. For example, for Unit tests only, do the following:
Add bootstrap: my_bootstrap_file.php to tests/unit.suite.yml:
# Codeception Test Suite Configuration
#
# Suite for unit or integration tests.
actor: UnitTester
bootstrap: my_bootstrap_file.php
modules:
enabled:
- Asserts
- \Helper\Unit
Call my_bootstrap_file.php something sensible like just bootstrap.php
Create tests/unit/my_bootstrap_file.php
<?php
\Codeception\Util\Autoload::addNamespace('', 'src');
The directory structure should look like this:
<project root>
src/
tests/
unit/
my_bootstrap_file.php
unit.suite.yml
Replace unit in the instructions above with acceptance, functional, etc. to apply it to different single components.
The PhpDoc for \Codeception\Util\Autoload::addNamespace():
/**
* Adds a base directory for a namespace prefix.
*
* Example:
*
* ```php
* <?php
* // app\Codeception\UserHelper will be loaded from
* '/path/to/helpers/UserHelper.php'
*
* Autoload::addNamespace('app\Codeception', '/path/to/helpers');
*
* // LoginPage will be loaded from '/path/to/pageobjects/LoginPage.php'
* Autoload::addNamespace('', '/path/to/pageobjects');
*
* Autoload::addNamespace('app\Codeception', '/path/to/controllers');
* ?>
* ```
*
* #param string $prefix The namespace prefix.
* #param string $base_dir A base directory for class files in the namespace.
* #param bool $prepend If true, prepend the base directory to the stack instead
* of appending it; this causes it to be searched
* first rather than last.
* #return void
*/
public static function addNamespace($prefix, $base_dir, $prepend = false)
If you want this to apply to your whole test suite, not just Unit tests, use codeception.yml instead of tests/unit.suite.yml, and tests/my_bootstrap_file.php instead of tests/unit/my_bootstrap_file.php.
<project root>
src/
tests/
my_bootstrap_file.php
codeception.yml

Laravel 4 DB:raw() is unavailable when running outside of framework

I'm using the [illuminate/database component][1] from Laravel 4 through composer - and while it generally works well, the DB facade seems to be broken in this standalone version. This meant I was unable to use static functions such as DB::raw(). It seems like the DB facade is even included in the package, but it doesn't work with ::raw().
I'm trying to do something like this -
...->orderBy(DB::raw('RAND()'))
Capsule::raw() is available, and is linked to the default connection's raw().
Also, what I did is I created a class:
/**
* #method static raw($value)
* #method static array select($query, $bindings = [], $useReadPdo = true)
* ...etc.
*/
class DB extends Manager
{
}
so that
You can use DB::raw().
IDE code completion works.
I found a partial solution, but if anyone has any ideas that work better, I'm eager to hear them (it seems the original Capsule package actually had support built in, maybe it was lost when it was merged, or maybe I'm using it incorrectly?)
use Illuminate\Database\Capsule\Manager as Capsule;
$connection = Capsule::connection();
// You can now use $connection->raw() in place of DB::raw()
...->orderBy($connection->raw('RAND()'))

Using PHP 5.3 namespaces (Doctrine2) with Zend Framework classes

i am having a situation where my doctrine model, Post, is in the namespace Application\Entities and i want to try to implement Zend_Acl_Resource_Interface. i get the error
Fatal error: Interface
'Application\Entities\Zend_Acl_Resource_Interface'
not found in
D:\Projects\Websites\php\ZendFram
ework\LearningZF\library\Application\Entities\Post.php
on line 8
namespace Application\Entities;
use DoctrineExtensions\NestedSet\Node;
/**
* #Entity #Table(name="posts")
*/
class Post implements Node, Zend_Acl_Resource_Interface {
update
if i try
class Post implements Node, \Zend_Acl_Resource_Interface {
Fatal error: Interface
'Zend_Acl_Resource_Interface' not
found in
D:\Projects\Websites\php\ZendFramework\LearningZF\library\Application\Entities\Post.php on
line 8
Are you using the ZF 2.0 branch or the stable one, e.g. 1.10? Is your autoloader setup to load classes with the ZF naming scheme?
You can use the Conversion tool the ZF devs used to convert ZF to using namespaces:
http://github.com/ralphschindler/PHPTools
http://blog.calevans.com/2010/03/27/zends-new-namespace-converter/
As far as I remember Zend Framework does not uses namespaces (until 2.x comes out anyway) so it's classes are in global namespace. Try class Post implements Node, \Zend_Acl_Resource_Interface {
i am going to put this as an answer, so i can mark this qn as answered if noone have any other answers, its actually a workaround i used. i am not too sure why it worked exactly, or rather why the Zend autoloader failed
i added the require_once to include Zend_Acl_Resource_Interface
namespace Application\Entities;
use DoctrineExtensions\NestedSet\Node;
require_once "Zend/Acl/Resource/Interface.php";
/**
* #Entity #Table(name="posts")
*/
class Post implements Node, \Zend_Acl_Resource_Interface {
i think a better fix will be to conversion tool in #Gordon's answer. but i cant fix all the errors i get with "unclean" conversion yet. paths are broken.

Categories