Symfony2.7, adding 3rd party lib to project - php

I'm stuck, i wanted to load external library to my symfony2 project but got error stating that class was not found my app/autoloader.php:
...
$loader->add('Tinify', __DIR__.'/../vendor/tinify/tinify/lib');
...
and my file where i want to use it looks like it:
<?php
namespace XYZ\NewsBundle\Controller;
...
use Tinify;
class NewsController extends Controller{
...
public function displayAction($slug)
{
$em = $this->getDoctrine()->getManager();
$external = new \Tinify();
}
error is as follow The autoloader expected class "Tinify" to be defined in file "xyz/app/../vendor/tinify/tinify/lib\Tinify.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
but file under vendor\tinify\tinify\lib\Tinify.php
namespace Tinify;
const VERSION = "1.3.0";
class Tinify {
...
}
i checked if it really has typo but don't see one

Full qualified class name of Tinify is not Tinify but \Tinify\Tinify. Its namespace + classname.
In you NewsController class you should do:
use \Tinify\Tinify;
Also note the backslash at the beginning of the namespace.
Then in the code you should use just class name and not namespace so also change this:
$external = new \Tinify();
to this:
$external = new Tinify();

Why don't install Tinyfy throught Composer?
composer require tinify/tinify
In this way composer handles de autoload of the library, you don't need to load manually nothing, you only must to make an instance of the class and run
$tinify = new Tinify();

Related

Codeception/AspectMock Parent class not found by locator

I have a problem with Codeception/AspectMock.
When using custom autoloader and try to create an instance of a class which has parent form the same custom namespace I have this error:
PHP Fatal error: Uncaught InvalidArgumentException: Class [parent
class name] was not found by locator in
vendor/goaop/parser-reflection/src/ReflectionEngine.php:112
I have very simple setup:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$kernel = AspectMock\Kernel::getInstance();
$kernel->init([
'debug' => true,
'includePaths' => [__DIR__. '/lib'],
]);
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
$b = new \lib\B();
Class \lib\B:
namespace lib;
class B extends A {}
Class \lib\A:
namespace lib;
class A
{
public function getName()
{
return static::class;
}
}
Class B is loaded via my custom autoloader, but then the locator tries to load parent class A via composer autoloader and returns this error. Is this a bug, or I'm doing something wrong?
The topic starter has already got an answer on GitHub.
In order to use custom autoloader you should re-init ReflectionEngine with composite class locator that will be able to locate your classes or you can use CallableLocator with closure for resolving paths.
Or, even better you could switch your code base to the PSR0/PSR-4
For example:
$kernel->loadFile(__DIR__ . '/autoload.php'); // custom autoloader
\Go\ParserReflection\ReflectionEngine::init(
new class implements \Go\ParserReflection\LocatorInterface {
public function locateClass($className) {
return (new ReflectionClass($className))->getFileName();
}
}
);
$b = new \lib\B(); // here you go
If you can easily do a find and replace on your codebase, maybe you could refactor your code to PSR-4 autoloading standards and do away with the need for a custom autoloader altogether.
This is the spec https://www.php-fig.org/psr/psr-4/. I'll try and explain it as simply as possible.
Imagine changing your lowercase namespace lib to Lib, and setting that namespace to the src/ directory in your composer.json:
"autoload": {
"psr-4": {
"Lib\\": "src/"
}
}
After setting that, run composer dumpautoload. Then all you need to do is search and replace namespace lib;, replacing with namespace Lib;.
An example class located in src/Form.php would have namespace Lib; at the top, followed by class Form.
<?php
namepace Lib;
class Form
{
// code
}
Namespaces use the folder naming convention. All classes directly in src/ have namespace Lib;. If there are subdirectories, the directory name becomes part of the namespace. For example a file in src/Form/Field/Text.php would have namespace Lib\Form\Field; class Text {}.
<?php
namepace Lib\Form\Field;
class Text
{
// code
}
You can see the full convention in the link above, but the general rule is make any folders begin with a capital letter, as with your classname, and the autoloader should be able to find all of your classes.
This is probably the best practice solution for you, and again as I said, only requires a little bit of file renaming and namespace tweaking. Good luck!

Importing custom class inside a controller

I created a class at Controller folder of Cake project like this:
<?php
class Hi
{
function __construct(){ }
public function hi()
{
echo "hi!";
exit;
}
}
Then in a controller, I tried to include it:
<?php
namespace App\Controller;
use App\Controller\AppController;
include_once "Hi.php";
class MyController extends AppController
{
public function sayHi()
{
$a = new Hi();
$a.hi();
}
}
Here is the error I'm having:
Fatal error: Cannot declare class Hi, because the name is already in use in path\api\src\Controller\Hi.php on line 2
What's going on?
MyController.php and Hi.php are in the same folder. I'm using PHP 7.
Including a file won't make the classes in that file part of the current namespace, as namespaces are a per-file functionality.
http://php.net/...namespaces.importing.php#language.namespaces.importing.scope
Your Hi class will be declared in the global namespace, and your new Hi() will cause PHP to look for it in the current namespace, ie it will look for App\Controller\Hi, which doesn't exist, hence the composer autoloader kicks in, and will map this via a PSR-4 namespace prefix match to src/Controller/Hi.php, which will include the file again, and that's when it happens.
http://www.php-fig.org/psr/psr-4/
Long story short, while using new \Hi() would fix this, you better not include class files manually, or declare them in paths where they do not belong. Instead declare your files and classes in a proper autoloading compatible fashion, that is for example with a proper namespace in a path that matches that namespace, like
namespace App\Utils;
class Hi {
// ...
}
in
src/Utils/Hi.php

Are namespaces in PHP "inherited"?

EDIT:
Yes the problem was using \ at the beginning of the use statement. As M1ke pointed out, use goes from the root element.
Original post
I think is a PHP question but it may be Drupal.
I'm working on a headless Drupal project where is using a class (which I call Entity Model) that uses a Drupal class called EntityFieldQuery.
Before a create or use this class I bootstrap Drupal using:
require_once DRUPAL_ROOT.'/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
The entity model class is in the Models names space like so:
namespace Models;
use \EntityFieldQuery;
class EntityModel
{
.....
$query = new EntityFieldQuery();
$query->doSomething();
......
}
The EntityFieldQuery is found perfectly as I use the "\" because this class is out of the Models namespace.
The problem is when this class is created is uses other classes that don't use any namespace, and I have the following error:
class Models\InsertQuery not found in ....
Here is the class used by EntityFieldQuery that uses InsertQuery
class InsertQuery_mysql extends InsertQuery ...
I don't understand why InsertQuery_mysql is found but InsertQuery
I ended up adding a "\" in InsertQuery to fix the problem like so:
class InsertQuery_mysql extends \InsertQuery ...
Actually this class in a php file called query.inc that contains two defitinion classes (in the same file, I don't know this is a a problem too)
class InsertQuery_mysql extends InsertQuery
....
class TruncateQuery_mysql extends TruncateQuery
I thought that if I use "new \ClassName()" the "default namespace" inside this class would be "\" too and not the first called class's namespace.
I don't like to modify 3rd party libraries, is any way to avoid this? I guess is a architecture problem rather than a lack of definition if someone has a better idea, I appreciate.
Thanks!
EDIT2: Adding more info...
In order of execution.
index.php:
require_once 'vendor/autoload.php';
require_once DRUPAL_ROOT.'/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
...
app/SiteController.php:
use Models\Campaign;
class SiteController {
...
$campaing = new Campaign();
...
app/Models/Campaing.php:
namespace Models;
class Campaign extends EntityModel {
...
app/Models/EntityModel.php:
namespace Models;
use \EntityFieldQuery; //<-- this should go without \ as I say in EDIT section
class EntityModel {
...
public function getAll() {
$query = new EntityFieldQuery(); //<--throwed Models\InsertQuery not found. It must have \ at the beginning of the class name.
To answer the base question (and pending further code) PHP namespaces are set by whichever namespace is declared in the file.
// Bar.php
namespace Foo;
class Bar {}
// some other file
use Foo\Bar;
$test = new Bar(); //works
// different file
namespace Foo;
$test = new Bar(); // works
// another file
require 'Bar.php';
// won't work because we are not in namespace "Foo"
$test = new Bar();
In your specific case it the use \EntityLoader should be use EntityLoader because you're exiting the namespace you want to be inside.

Laravel 5: Using a controller in a view composer - controller class not found

I followed these instructions and created a view composer for my default layout.
My DefaultComposer.php is located under app/Http/ViewComposers, hence the namespace used below:
<?php namespace App\Http\ViewComposers;
use Illuminate\Contracts\View\View;
class DefaultComposer {
public function compose(View $view) {
$data['language'] = LanguageController::getDefaultLanguage();
$view->with($data);
}
}
?>
Now, when I load a page, I get the following error:
Class 'App\Http\ViewComposers\LanguageController' not found
This happens because the LanguageController.php is placed under app/Http/Controllers, which is a different namespace.
How can I use the LanguageController class in my DefaultComposer?
Update:
Using this declaration:
use App\Http\Controllers\LanguageController as LanguageController;
throws: Class 'App\Http\Controllers\LanguageController' not found. I'm confused.
I figured this out. As the controllers in my application live in the global namespace, all I needed to do is add a backslash in front of the class name.
So instead of this:
$data['language'] = LanguageController::getDefaultLanguage();
I did this:
$data['language'] = \LanguageController::getDefaultLanguage();

Using namespaces in Laravel 4

I'm new to Laravel and using PHP namespaces in general. I didn't run into any problems until I decided to make a model named File. How would I go about namespacing correctly so I can use my File model class?
The files are app/controllers/FilesController.php and app/models/File.php. I am trying to make a new File in FilesController.php.
Namespacing is pretty easy once you get that hang of it.
Take the following example:
app/models/File.php
namespace App\Models;
class File {
public function someMethodThatGetsFiles()
{
}
}
app/controllers/FileController.php
namespace App\Controllers;
use App\Models\File;
class FileController {
public function someMethod()
{
$file = new File();
}
}
Declare the Namespace:
namespace App\Controllers;
Remember, once you've put a class in a Namespace to access any of PHP's built in classes you need to call them from the Root Namespace. e.g: $stdClass = new stdClass(); will become $stdClass = new \stdClass(); (see the \)
"Import" other Namespaces:
use App\Models\File;
This Allows you to then use the File class without the Namespace prefix.
Alternatively you can just call:
$file = new App\Models\File();
But it's best practice to put it at the top in a use statement as you can then see all the file's dependencies without having to scan the code.
Once that's done you need to them run composer dump-autoload to update Composer's autoload function to take into account your newly added Classes.
Remember, if you want to access the FileController via a URL then you'll need to define a route and specify the full namespace like so:
Route::get('file', 'App\\Controllers\\FileController#someMethod');
Which will direct all GET /file requests to the controller's someMethod()
Take a look at the PHP documentation on Namespaces and Nettut's is always a good resource with this article
first, load your class with:
$ composer dump-autoload
then
$file = new File;
// your stuff like:
$file->name = 'thename';
$file->active = true;
$file->save();
Section: Insert, Update, Delete on Laravel 4 Eloquent's doc
To namespace your model, at the top of your model class right after the opening
Then when you call from controllers you will call new Whatever\Model;
You probably have to do a dump-autoload with composer the first time around.
have a look to it.. hopefully will clear your query....
<?php
namespace app\controllers;
use yii\web\Controller;
use app\models\users;
class UserController extends Controller{
public function actionIndex()
{
echo "working on .....";
}
}
Namespaces are defined at the top of PHP classes right after the opening php script tag like this:
<?php
namespace MyNameSpace;
When you then want to use the namespaced class in some other class, you define it like this:
new MyNameSpace\PhpClass;
or import it at the top of the file (after namespaces if present) like this:
<?php
//namespace
use MyNameSpace\MyPHPClass;
//then later on the code you can instantiate the class normally
$myphpclass = new MyPHPClass();
In Laravel namespaces can be defined anywhere composer can autoload them, I'd recommend defining namespaces within the app directory. So you can define a namespace like Utils for holding Utility classes by creating a Utils directory in the app directory, creating our utility classes and defining the namespace as we did above.
Afterwards you have run the command to ask composer to autoload classes:
$ composer dump-autoload

Categories