I'm trying to use the php-ga third-party library in my symfony project. I've installed the library in apps/<app>/lib, cleared the cache, and the third-party files are appearing as I would expect in config_autoload.yml.php:
'tracker' => 'C:/wamp/www/apps/api/lib/php-ga/GoogleAnalytics/Tracker.php',
'transaction' => 'C:/wamp/www/apps/api/lib/php-ga/GoogleAnalytics/Transaction.php',
...
However, when I try to use the classes in an action under the same app like so:
use UnitedPrototype\GoogleAnalytics;
public function executeNew(sfWebRequest $request)
{
$tracker = new GoogleAnalytics\Tracker(...);
...
I get an error saying it can't resolve the class:
Fatal error: Class 'UnitedPrototype\GoogleAnalytics\Tracker' not found in C:\wamp\www\apps\api\modules\encoding\actions\actions.class.php
What am I missing?
Symfony's autoloader can not load namespaced classes properly. I think you should move the ga lib to lib/vendor/php-ga and use it's own autoloader in config/ProjectConfiguration.class.php (like require_once __DIR__ . '/../lib/vendor/php-ga/autoload.php').
Related
So subject is the question. Yes, I've searched this forum and googled too. All I've got - useless Symfony docs and casts, some general advises, cli-s and nothing case specific. Maybe yahoo or duckduck could help better?
Everyone is talking about bundles, about how it is important to create them, probably because under the hood Symfony is pushing users away from custom libraries, but no one is actually explains how to start using a bundle - how to start calling its methods.
No, my library is not a composer or whatever package. No, library methods do not return Response objects. No, I am not dealing with composer or recompilations or cli (I use Composercat). No, I will not put library to github or packagist to load it via composer or whatever because it is private library.
Sorry about emotional off-topic.
About the case: I've put my library into the folder
src/lib/MyLibrary.php
I suspect that library class is autoloaded, because if I do not extend Controller with it (if I declare class MyLibrary instead of class MyLibrary extends Controller) - Symfony spits "class name in use" error.
So question: in my controller how to call library method?
$this->get('MyLibrary') doesn't work.
echo print_r($this) doesn't show MyLibrary in this registry too.
Looks like library file is loaded but not registered and/or instantiated. If it is so, then where to point Symfony to register it?
So most of this question is really about how php manages classes. Not so much about Symfony. But that's okay.
To start with it would be best to move project/src/lib to just project/lib. Symfony has some scanning stuff going on in the src directory and you really don't want to have your library mixed up in it.
So:
# lib/MyLibrary.php
namespace Roman;
class MyLibrary
{
public function hello()
{
return 'hello';
}
}
Notice that I added a namespace (Roman) just to distinguish your code from Symfony's.
Now you need to tweak composer.json in order to allow php to autoload your classes:
"autoload": {
"psr-4": {
"App\\": "src/",
"Roman\\": "lib/"
}
},
After adding the Roman line, run "composer dump-autoload" to regenerate the autoload files.
After that, it's just a question of using regular php inside of your application:
# src/Controller/DefaultController.php
namespace App\Controller;
use Roman\MyLibrary;
use Symfony\Component\HttpFoundation\Response;
class DefaultController
{
public function index()
{
$myLibrary = new MyLibrary();
$hello = $myLibrary->hello();
return new Response($hello);
}
}
And that should get your started.
I'm using a 3rd party extension like so:
(This is inside my controller)
require_once Yii::$app->basePath.'/vendor/campaignmonitor/createsend-php/csrest_subscribers.php';
$wrap = new CS_REST_Subscribers($list_id, $auth);
However, this is returning an error that CS_REST_subscribers class is not found.
How do I use this class correctly when the class is inside the file. Unfortunately this extension is older and is not namespaced.
You need to install it using composer with the following command
composer require "campaignmonitor/createsend-php" "6.0.0"
It uses the simplest way, i.e autoloads each class separately. we define the array of paths to the classes that we want to autoload in the composer.json file and if you see the vendor/campaignmonitor/createsend-php/composer.json file inside the package directory
"autoload": {
"classmap": [
"csrest_administrators.php",
"csrest_campaigns.php",
"csrest_clients.php",
"csrest_general.php",
"csrest_events.php",
"csrest_lists.php",
"csrest_people.php",
"csrest_segments.php",
"csrest_subscribers.php",
"csrest_templates.php",
"csrest_transactional_classicemail.php",
"csrest_transactional_smartemail.php",
"csrest_transactional_timeline.php"
]
}
so you won't need the include or require statement, you can directly call any class you want for instance adding the following lines inside your action or view
$authorize_url = CS_REST_General::authorize_url(
'1122',//'Client ID for your application',
'http://example.com/redirect-page',//Redirect URI for your application,
'ViewReports'//The permission level your application requires,
);
print_r($authorize_url);
prints the following
https://api.createsend.com/oauth?client_id=1122&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect-page&scope=ViewReports
For knowledge base if you want to use a Third-party code that is not using autoloader or psr4 you can go through the Yii tutorial
I have added the Stripe library to my composer.json file, ran all commands just to check... update, dump-autoload etc.
In my classmap file the library is shown:
'Stripe\\Account' => $vendorDir . '/stripe/stripe-php/lib/Account.php',
and so on...
In my app folder i have my classes folder etc:
app
motivate
Billing
BillingInterface.php
StripeBilling.php
In my StripeBilling file I reference Stripe like so:
<?php
namespace Motivate\Billing;
class StripeBilling implements BillingInterface
{
public function __construct()
{
Stripe::setApiKey(Config::get('stripe.secret_key'));
}
This throws the error:
Class 'Motivate\Billing\Stripe' not found
So my next thought was:
use \Stripe as Stripe;
Which returns class Stripe not found.
Where is this going wrong? Thanks :)
According to the documentation:
To use your API key, you need only call \Stripe\Stripe::setApiKey()
with your key. The PHP library will automatically send this key in
each request.
So, just try using use \Stripe\Stripe as Stripe; instead.
I went through the Phalcon docs and got PHPUnit set up and working. However, I'm having trouble bootstrapping my existing services into the unit testing framework.
Currently, I load my config, routes, and services in the /public/index.php. For example, I'm loading the session library:
$di->set(
'session',
function () use ( $config ) {
$session = new Phalcon\Session\Adapter\Redis(
... config ...
);
});
So now, in my application I'd have code that calls $this->session->get( 'user_id' ) to use the session library. I have many of these services -- one for SQL, MongoDB, cookies, etc.
The problem I'm having is correctly loading these services into the unit testing class. The Phalcon docs recommend loading my DI services in the UnitTestCase class (explained here) but I really do not want re-define the same services in this class loader. Additionally, I want to use the components in my application in the same ways; those components rely on the services being lazy-loaded.
So, to attempt this, I include the same /app/config/services.php file in my unit testing TestHelper.php init script thinking that I can just use the same $di object. This works in that my test cases can call $this->di->getSession()->get( 'var' ) but as soon as a component in my app tries to call $this->session->get( 'var' ) it throws an error:
1) Libraries\SessionTest::testGetSet
Undefined property: Libraries\SessionTest::$session
/home/mike/PhalconProject/app/library/Session.php:25
/home/mike/PhalconProject/tests/libraries/SessionTest.php:13
This error is telling me that my application session-management library Session.php is failing when accessing $this->session-> via the dependency injector.
Is there something I'm fundamentally doing wrong here? Do I need to redefine the services in my unit testing class? And if I do need to redefine them, will my application be able to load its services?
So the solution here seems to be structuring the application libraries to statically access the DI services.
The first step was to set the default DI in /public/index.php and /tests/bootstrap.php:
\Phalcon\DI::setDefault( $di );
Now, in the application libraries (like /app/Library/Auth.php or /app/Library/Session.php) the services are accessed statically (more info here in the Phalcon docs):
$session = \Phalcon\DI::getDefault()->getSession();
$session->get( 'user_id' )
...
To make this easier, I set up a base library that all of my application libraries extend. The base library has a method to simplify this call.
namespace Base;
use \Phalcon\DI as DI;
class Library extends \Phalcon\Mvc\User\Component
{
public function getService( $service )
{
$func = "get". ucfirst( $service );
return DI::getDefault()->$func();
}
}
Finally, /app/Library/Session.php would extend this \Base\Library class, and whenever I need the session service in a method I can just call:
$session = self::getService( 'session' );
I have injected all my Phalcon services (which i usually get by calling DI object) using the simple PHPUnit bootstrap.php file (take a look at --bootstrap option of PHPUnit) my bootstrap.php contents is:
<?php
require_once(__DIR__ . '/../app/config/local_config.php');
$config = include __DIR__ . "/../app/config/config.php";
/**
* Read auto-loader
*/
include __DIR__ . "/../app/config/loader.php";
/**
* Read services
*/
include __DIR__ . "/../app/config/services.php";
Thus, in my PHPUnit tests i just call $di->get('MyService');
I'm trying to create my own library in a Symfony2 project but I'm having a hard time doing so...
Basically I want to reuse an FTP browser class I made for another project.
I copied the class into
/vendor/mylib
and tried to autoload it like that
$loader->registerPrefixes(array(
'Twig_Extensions_' => __DIR__.'/../vendor/twig-extensions/lib',
'Twig_' => __DIR__.'/../vendor/twig/lib',
'Mylib_' => __DIR__.'/../vendor/mylib'
));
I then tried to instantiate a Mylib_Test object inside my bundle's controller and I got this error :
Fatal error: Class 'Test\FrontBundle\Controller\Mylib_Test' not found in /Applications/MAMP/htdocs/sf2_project/src/Test/FrontBundle/Controller/WelcomeController.php on line 26
Anyone has an idea on how to do this ?
You probably have namespace Test\FrontBundle\Controller; in your controller. When you call for some class php tries to find it in specified namespace. Mylib_Test is obviously not in that namespace. So you should implicitly indicate that this class should be looked for in global namespace. In order to do that you should prepend class name with backslash:
$instance = new \Mylib_Test();
More info in docs