I am trying to just check out the symfony event dispatcher class and i have been following this online tutorial , so i have the following in my index.php file:
<?php
require('vendor/autoload.php');
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher;
$dispatcher->addListener('UserSignedUp' , function(Event $event){
// die('Handling It !!');
var_dump($event);
});
$event = new App\Events\UserSignedUp( (object) [ 'name' => 'gautam' , 'email' => 'gautamz07#yahoo.com' ] );
$dispatcher->dispatch('UserSignedUp' , $event);
and i have the following directory structure:
event_dis
- app
- events
- UserSignUp.php
- vendor
- index.php
- composer.json
I have the following in my composer.json file:
{
"require": {
"symfony/event-dispatcher": "^3.2"
},
"autoload" : {
"psr-4" : {
"App\\" : "app/"
}
}
}
The UserSignedUp.php class looks like the following :
<?php
namespace App\Events;
class UserSignedUp extends Event {
public $user;
public function __construct($user) {
$this->user = $user;
}
}
Now since i have the following line in my index.php file:
$event = new App\Events\UserSignedUp( (object) [ 'name' => 'gautam' , 'email' => 'gautamz07#yahoo.com' ] );
The UserSignedUp class gets called and i get the following error in my browser:
Class 'App\Events\Event' not found in C:\xampp\htdocs\symfony_compo\event_dis\app\Events\UserSignedUp.php on line 6
Now why am i getting this error , in the tutorial this same example works perfectly, but on my local machine this does't , can somebody tell me what am i doing wrong here ??
Event class does not exists in App\Events namespace. You should edit UserSignedUp.php and add use Symfony\Component\EventDispatcher\Event;:
<?php
namespace App\Events;
use Symfony\Component\EventDispatcher\Event;
class UserSignedUp extends Event {
public $user;
public function __construct($user) {
$this->user = $user;
}
}
Related
I'm trying to override a vendor file located at "vendor\cimpleo\omnipay-authorizenetrecurring\src\Objects\Schedule.php" to correct some issues.
composer.json
"autoload": {
"psr-4": {
"App\\": "app/",
"Cimpleo\\": "app/Overrides/"
},
"classmap": [
"database/seeds",
"database/factories",
"vendor/google/apiclient/src",
"vendor/google/apiclient-services/src/Google"
],
"exclude-from-classmap": ["vendor\\cimpleo\\omnipay-authorizenetrecurring\\src\\Objects\\Schedule.php"]
}
Then I copied and edited the Schedule.php to folder "app\Overrides".
namespace Cimpleo;
use Academe\AuthorizeNet\PaymentInterface;
use Academe\AuthorizeNet\AbstractModel;
use Omnipay\Common\Exception\InvalidRequestException;
use DateTime;
class Schedule extends AbstractModel
{
...
The vendor Schedule.php file looks like this.
namespace Omnipay\AuthorizeNetRecurring\Objects;
use Academe\AuthorizeNet\PaymentInterface;
use Academe\AuthorizeNet\AbstractModel;
use Omnipay\Common\Exception\InvalidRequestException;
use DateTime;
class Schedule extends AbstractModel
{
const SCHEDULE_UNIT_DAYS = 'days';
const SCHEDULE_UNIT_MONTHS = 'months';
protected $intervalLength;
protected $intervalUnit;
protected $startDate;
protected $totalOccurrences;
protected $trialOccurrences;
public function __construct($parameters = null) {
parent::__construct();
$this->setIntervalLength($parameters['intervalLength']);
$this->setIntervalUnit($parameters['intervalUnit']);
$this->setStartDate($parameters['startDate']);
$this->setTotalOccurrences($parameters['totalOccurrences']);
if (isset($parameters['trialOccurrences'])) {
$this->setTrialOccurrences($parameters['trialOccurrences']);
}
}
public function jsonSerialize() {
$data = [];
if ($this->hasIntervalLength()) {
$data['interval']['length'] = $this->getIntervalLength();
}
if ($this->hasIntervalUnit()) {
$data['interval']['unit'] = $this->getIntervalUnit();
}
if ($this->hasStartDate()) {
$data['startDate'] = $this->getStartDate();
}
if ($this->hasTotalOccurrences()) {
$data['totalOccurrences'] = $this->getTotalOccurrences();
}
if ($this->hasTrialOccurrences()) {
$data['trialOccurrences'] = $this->getTrialOccurrences();
}
return $data;
}
protected function setIntervalLength(int $value) {
if ($value < 7 || $value > 365) {
throw new InvalidRequestException('Interval Length must be a string, between "7" and "365".');
}
$this->intervalLength = (string)$value;
}
...
The class is instantiated here
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Omnipay\Omnipay;
use Omnipay\AuthorizeNetRecurring;
use Omnipay\AuthorizeNetRecurring\Objects\Schedule;
use Omnipay\Common\CreditCard;
class AuthorizeNetRecurringController extends Controller
{
private $gateway;
public function __construct() {
$this->gateway = Omnipay::create('AuthorizeNetRecurring_Recurring');
$this->gateway->setAuthName('3KJZb44jR');
$this->gateway->setTransactionKey('2fFqRA7w22a2G7He');
$this->gateway->setTestMode(true);
}
//
public function createSubscription(Request $request) {
$schedule = new Schedule([
//For a unit of days, use an integer between 7 and 365, inclusive. For a unit of months, use an integer between 1 and 12, inclusive.
'intervalLength' => '1',
// use values 'days' or 'months'
'intervalUnit' => 'months',
//date in format 'YYYY-mm-dd'
'startDate' => date("Y-m-d"), //'2020-03-10',
//To create an ongoing subscription without an end date, set totalOccurrences to "9999".
'totalOccurrences' => '12',
//If a trial period is specified, include the number of payments during the trial period in totalOccurrences.
'trialOccurrences' => '1',
]);
...
Then run composer dump-autoload. After running the script the app is still calling the vendor file that causes the error below. Composer changes doesn't seem to work.
Omnipay\Common\Exception\InvalidRequestException
Interval Length must be a string, between "7" and "365".
Omnipay\AuthorizeNetRecurring\Objects\Schedule::setIntervalLength
D:\xampp\htdocs\SBF_app_version1.5\vendor\cimpleo\omnipay-authorizenetrecurring\src\Objects\Schedule.php:56
Thanks
I think you have to import the overridden class, instead of the original one.
use Cimpleo\Schedule;
// use Omnipay\AuthorizeNetRecurring\Objects\Schedule;
But a better solution to this problem would be to use inheritance:
namespace App\Overrides\Cimpleo;
use Omnipay\AuthorizeNetRecurring\Objects\Schedule as BaseSchedule;
class Schedule extends BaseSchedule
{
...
}
And then in the controller you would import the new Schedule class:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Omnipay\Omnipay;
use Omnipay\AuthorizeNetRecurring;
use App\Overrides\Cimpleo\Schedule;
use Omnipay\Common\CreditCard;
class AuthorizeNetRecurringController extends Controller
{
...
}
Also you would have to remove the new autoloading instruction and also exclude-from-classmap in composer. Just autoload app directory and it would be enough:
"autoload": {
"psr-4": {
"App\\": "app/"
},
I don't understand Why I can't create custom services. I get errors with the both technic. I don't find anything about that in your doc.
# app/config/services.yml
services:
jdf.utils.phphelper:
class: JDF\Utils\PhpHelper
// src/JDF/Utils/PhpHelper.php
namespace JDF\Utils;
class PhpHelper
{
/**
* [pdebug description]
* #param string $var The string to beautiful show
* #param string $msg Description of the $var
* #param integer $displayNone
* #return echo pre print_r $var string
*/
public function pdebug ($var, $msg = '', $displayNone = 0) {
}
}
Case 1 : (Pass PhpHelper in the __construct function)
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use JDF\Utils\PhpHelper;
use Psr\Log\LoggerInterface;
/**
*
*/
class ImportController extends Controller {
function __construct(
PhpHelper $PhpHelper
) {
}
public function indexAction() {
//$test = $this->container->get('jdf.utils.phphelper');
return new Response('<hr>');
}
} /*End of class*/
Error 1 :
Catchable Fatal Error: Argument 1 passed to JDF\CsvTreatmentBundle\Controller\ImportController::__construct() must be an instance of JDF\Utils\PhpHelper, none given, called in C:\kitutilitaire\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Controller\ControllerResolver.php on line 202 and defined
500 Internal Server Error - ContextErrorException
Case 2 (just use get() controller method) :
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use JDF\Utils\PhpHelper;
use Psr\Log\LoggerInterface;
/**
*
*/
class ImportController extends Controller {
function __construct(
//PhpHelper $PhpHelper
// LoggerInterface $logger
) {
}
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
// $logger = $this->container->get('logger');
return new Response('<hr>');
}
} /*End of class*/
Error 2 :
Attempted to load class "PhpHelper" from namespace "JDF\Utils".
Did you forget a "use" statement for another namespace?
Stack Trace
in var\cache\dev\appDevDebugProjectContainer.php at line 3555 -
*/
protected function getJdf_Utils_PhphelperService()
{
return $this->services['jdf.utils.phphelper'] = new \JDF\Utils\PhpHelper();
}
/**
EDIT : composer.json autoload
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle/",
"JDF\\CsvTreatmentBundle\\": "src/JDF/CsvTreatmentBundle/",
"JDF\\Utils\\": "src/JDF/Utils/PhpHelper"
},
"classmap": ["app/AppKernel.php", "app/AppCache.php"]
},
Thank in advence for your help.
Controllers do not get any injection by default. They have $this->container always available to get to all your services.
So nothing more to do than:
class ImportController extends Controller {
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
// $logger = $this->container->get('logger');
return new Response('<hr>');
}
}
FYI: The cache file appDevDebugProjectContainer is auto generated and of no significance to your problem.
I've solved the problem with change my composer.json.
For can use $this->container->get('jdf.utils.phphelper'); the all good code is :
# app/config/services.yml
services:
jdf.utils.phphelper:
class: JDF\Utils\PhpHelper
// src/JDF/Utils/PhpHelper.php
namespace JDF\Utils;
class PhpHelper {}
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use JDF\Utils\PhpHelper;
/**
*
*/
class ImportController extends Controller {
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
return new Response('<hr>');
}
} /*End of class*/
AND IMPORTANT : The composer.json :
"autoload": {
"psr-4": {
"JDF\\CsvTreatmentBundle\\": "src/JDF/CsvTreatmentBundle/",
"JDF\\Utils\\": "src/JDF/Utils/"
},
"classmap": ["app/AppKernel.php", "app/AppCache.php"]
},
And the CLI command : php composer.phar dump-autoload
Thank to colburton for this time and interest at my issue.
I am trying to plug APCu into the Symfony 3.3 test project.
I am getting an error, when I add ApcuAdapter to AppKernel.php.
Here is the list of what I have done:
in ./app/AppKernel.php i have added a "new" line to $bundles in public function registerBundles():
public function registerBundles()
{
$bundles = [
... ,
new Symfony\Component\Cache\Adapter\ApcuAdapter()
];
...
return $bundles;
}
Opened the project's site. It shows an error:
Attempted to call an undefined method named "getName" of class "Symfony\Component\Cache\Adapter\ApcuAdapter".
(./ means the root folder of the project)
Please, tell me why does this error happen and how to plug this adapter into the symfony framework. Thank you.
me have found the solution somewhere on the framework's website.
somehow, we should use not the Adapter, but the Simple instead.
seems very un-logical to me.
so, the Service now works and looks this way:
<?php
namespace AppBundle\Service;
use Symfony\Component\Cache\Simple\ApcuCache;
class ApcuTester
{
public function __construct
(
)
{
}
public function testMe()
{
$cache = new ApcuCache();
$TestVar_dv = 0;
$TestVar_vn = 'TestVar';
$TestVar = NULL;
//$cache-> deleteItem($TestVar_vn); // dbg
// Read
if ( $cache->hasItem($TestVar_vn) )
{
$TestVar = $cache->get($TestVar_vn);
}
else
{
$cache->set($TestVar_vn, $TestVar_dv);
$TestVar = $TestVar_dv;
}
// Modify
$TestVar++;
// Save
$cache->set($TestVar_vn, $TestVar);
// Return
return $TestVar;
}
}
And the Controller which executes this Service looks as this:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Service\MessageGenerator;
use AppBundle\Service\ApcuTester;
class LuckyController extends Controller
{
/**
* #Route("/lucky/number", name="lucky")
*/
public function numberAction
(
Request $request,
MessageGenerator $messageGenerator,
ApcuTester $apcuTester
)
{
$lucky_number = mt_rand(0, 100);
$message = $messageGenerator->getHappyMessage();
$testvar = $apcuTester->testMe();
$tpl = 'default/lucky_number.html.twig';
$tpl_vars =
[
'lucky_number' => $lucky_number,
'message' => $message,
'testvar' => $testvar
];
return $this->render($tpl, $tpl_vars);
}
}
If i wrote the same thing in pure PHP i would have done it an hour earlier :) Oh these crazy frameworks...
I just started using Slim Framework to create my rest API. Everything works well until I try to route HTTP request to a static class method (I used the anonymous function before). Below is my new route code on index.php:
include "vendor/autoload.php";
$config = ['settings' => [
'addContentLengthHeader' => false,
'displayErrorDetails' => true,
'determineRouteBeforeAppMiddleware' => true
]
];
$app = new \Slim\App($config);
$app->get('/user/test', '\App\Controllers\UserController:test');
$app->run();
And below is my UserController class on UserController.php
class UserController{
public function test($request, $response, $args){
$array = ['message'=>'your route works well'];
return $response->withStatus(STAT_SUCCESS)
->withJson($array);
}
}
Error details:
Type : RuntimeException
Message: Callable \Controllers\UserController does not exist
File : /var/www/html/project_api/vendor/slim/slim/Slim/CallableResolver.php
Below is my project folder tree
project_api/
index.php
vendor/
slim/slim/Slim/CallableResolver.php
Controllers/
UserController.php
my composer.json
{
"require": {
"slim/slim": "^3.8",
"sergeytsalkov/meekrodb": "*",
"slim/http-cache": "^0.3.0"
}
},
"autoload": {
"psr-4": {
"Controllers\\": "Controllers/"
}
}
It seems that your namespace is define improperly. In your composer.json, class UserController under the namespace Controllers.
you should define a namespace at the top of your UserController.php:
namespace Controllers;
and change $app->get() in your index.php to:
$app->get('/user/test', 'Controllers\UserController:test');
I'm using Slim Framework 3 to create an API. The app structure is: MVCP (Model, View, Controller, Providers).
Is it possible to have Slim Dependency Inject all my classes?
I'm using composer to autoload all my dependencies.
My directory structure looks like this:
/app
- controllers/
- Models/
- services/
index.php
/vendor
composer.json
Here's my composer.json file.
{
"require": {
"slim/slim": "^3.3",
"monolog/monolog": "^1.19"
},
"autoload" : {
"psr-4" : {
"Controllers\\" : "app/controllers/",
"Services\\" : "app/services/",
"Models\\" : "app/models/"
}
}
}
Here's my index.php file. Again, the dependencies are being auto injected by composer
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
$container = new \Slim\Container;
$app = new \Slim\App($container);
$app->get('/test/{name}', '\Controllers\PeopleController:getEveryone');
$app->run();
My controller looks like this
<?php #controllers/PeopleController.php
namespace Controllers;
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
class PeopleController
{
protected $peopleService;
protected $ci;
protected $request;
protected $response;
public function __construct(Container $ci, PeopleService $peopleService)
{
$this->peopleService = $peopleService;
$this->ci = $ci;
}
public function getEveryone($request, $response)
{
die($request->getAttribute('name'));
return $this->peopleService->getAllPeoples();
}
}
My PeopleService file looks like this:
<?php
namespace Services;
use Model\PeopleModel;
use Model\AddressModel;
use Model\AutoModel;
class PeopleService
{
protected $peopleModel;
protected $autoModel;
protected $addressModel;
public function __construct(PeopleModel $peopleModel, AddressModel $addressModel, AutoModel $autoModel)
{
$this->addressModel = $addressModel;
$this->autoModel = $autoModel;
$this->peopleModel = $peopleModel;
}
public function getAllPeopleInfo()
{
$address = $this->addressModel->getAddress();
$auto = $this->autoModel->getAutoMake();
$person = $this->peopleModel->getPeople();
return [
$person[1], $address[1], $auto[1]
];
}
}
Models/AddressModels.php
<?php
namespace Model;
class AddressModel
{
public function __construct()
{
// do stuff
}
public function getAddress()
{
return [
1 => '123 Maple Street',
];
}
}
Models/AutoModel.php
namespace Model;
class AutoModel
{
public function __construct()
{
// do stuff
}
public function getAutoMake()
{
return [
1 => 'Honda'
];
}
}
Models/PeopleModel.php
<?php
namespace Model;
class PeopleModel
{
public function __construct()
{
// do stuff
}
public function getPeople()
{
return [
1 => 'Bob'
];
}
}
ERROR
I'm getting the following error now:
PHP Catchable fatal error: Argument 2 passed to Controllers\PeopleController::__construct() must be an instance of Services\PeopleService, none given, called in /var/www/vendor/slim/slim/Slim/CallableResolver.php on line 64 and defined in /var/www/app/controllers/PeopleController.php on line 21
THE QUESTION
How do I dependency inject all my classes? Is there a way to automagically tell Slim's DI Container to do it?
When you reference a class in the route callable Slim will ask the DIC for it. If the DIC doesn't have a registration for that class name, then it will instantiate the class itself, passing the container as the only argument to the class.
Hence, to inject the correct dependencies for your controller, you just have to create your own DIC factory:
$container = $app->getContainer();
$container['\Controllers\PeopleController'] = function ($c) {
$peopleService = $c->get('\Services\PeopleService');
return new Controllers\PeopleController($c, $peopleService);
};
Of course, you now need a DIC factory for the PeopleService:
$container['\Services\PeopleService'] = function ($c) {
$peopleModel = new Models\PeopleModel;
$addressModel = new Models\AddressModel;
$autoModel = new Models\AutoModel;
return new Services\PeopleService($peopleModel, $addressModel, $autoModel);
};
(If PeopleModel, AddressModel, or AutoModel had dependencies, then you would create DIC factories for those too.)