I'm trying to include a PHP class in magento 2.
I use a require_once and create a folder lib in the root of my module and there I put the folder that contains the class 'lib / Meli / Meli.php'
Also try in the project folder 'lib / lib_web / Meli / Meli.php'
All without success, any suggestion
This is my controller 'Controller / Adminhtml / Action / publicar.php'
<?php
namespace Uno\MercadoLibre\Controller\Adminhtml\Action;
use \Magento\Backend\App\Action;
class publicar extends Action {
protected $_session;
protected $_filesystem;
protected $_directoryList;
/**
* #param Action\Context $context
*/
public function __construct(
Action\Context $context,
\Magento\Framework\Filesystem\DirectoryList $directoryList,
\Magento\Framework\Filesystem $filesystem,
\Magento\Customer\Model\Session $session
) {
parent::__construct($context);
$this->_directoryList = $directoryList;
$this->_filesystem = $filesystem;
$this->_session = $session;
}
/**
* {#inheritdoc}
*/
protected function _isAllowed() {
return $this->_authorization->isAllowed('Uno_MercadoLibre::action_publicar');
}
/**
* Publicar action
*
* #return \Magento\Framework\Controller\ResultInterface
*/
public function execute() {
$appId = '123';
$secretKey = 'abcdefghijkl';
$redirectURI = 'https://example.mx';
$siteId = 'MLM';
//$path = $this->_directoryList->getPath('lib_web');
//echo "PATH " . $path.'/Meli/Meli.php';
//require_once($path.'/Meli/Meli.php');
//$libPath = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::LIB)->getAbsolutePath();
$mediapath = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::APP)->getAbsolutePath();
$modulePath = $mediapath.'code/Uno/MecadoLibre/lib/Meli/Meli.php';
echo $modulePath;
require_once($modulePath);
$meli = new Meli($appId, $secretKey);
$params = array();
$url = '/sites/' . $siteId;
$result = $meli->get($url, $params);
echo '<pre>';
print_r($result);
echo '</pre>';
die();
}
}
?>
the path of the class returns to me, but it does not help me for the require_once
/var/inetpub/example.mx/app/code/Uno/MecadoLibre/lib/Meli/Meli.php
I think the solution of your problem the composer.
Please check it the accepted answer:
How to I use Composer to autoload classes from outside the vendor?
Thank you, your information, I told you how I resolved this.
In my class Meli.php add:
namespace Uno\MercadoLibre\Controller\Adminhtml\Action;
In my controller add:
use \Uno\MercadoLibre\Lib\Meli\Meli;
Object Manager
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $ml_session = $ objectManager->create('\Uno\MercadoLibre\Lib\Meli\Meli', ['client_id' => $ appId, 'client_secret' => $ secretKey, 'access_token' => $ accessToken]);
Related
I try to load all the routes from all Bundles in a specific namespace dynamically. So I set up a CustomRoute Loader as a service and determine there which route to add. But the PhpFileLoader can´t find the Bundle. I get the name of thee Bundles with $this->container->getParameter('kernel.bundles'); so there can´t be a typo. Loading these Bundles hardcoded from within the routing.php works fine but not from the service class. Inside of the routing.php I can´t determine with Bundles are loaded, so using only the routing.php is not a solution. What do I miss? This is my code so far:
Routing.php
<?php
// app/config/routing.php
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
$path = "/Controller/";
$defaultAnnotationRoutes = [
'SomeDefaultBundle'];
$routes = new RouteCollection();
$routes->add('somedefaulRoute', new Route('/', array(
'_controller' => 'SomeDefaultBundle:Welcome:page',
)));
$routes->addCollection(
$loader->import("#FOSJsRoutingBundle/Resources/config/routing/routing.xml"
));
foreach ($defaultAnnotationRoutes as $bundleName) {
$routingConfigPath = "#" . $bundleName . $path;
$routes->addCollection(
// loads routes from the given routing file stored in some bundle
$loader->import($routingConfigPath, "annotation"));
}
$routes->addCollection(
$loader->import('mapbender.routing_loader:load', "service"));
return $routes;
ServiceClass:
namespace Mapbender\CoreBundle\Routing;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
use Symfony\Component\Config\Exception\FileLoaderLoadException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Routing\Loader\PhpFileLoader;
use Symfony\Component\Routing\RouteCollection;
class BundleLoader
{
protected $container;
protected $path = "/Controller/";
protected $loader;
/**
* BundleLoader constructor.
*
* #param $container
*/
public function __construct($container)
{
$this->container = $container;
$rootdir = $this->container->get('kernel')->getRootDir();
$this->loader = new PhpFileLoader(new FileLocator());
}
/**
* #param $resource
* #param null $type
* #return RouteCollection
*/
public function load($resource, $type = null)
{
$routes = new RouteCollection();
$bundles = $this->container->getParameter('kernel.bundles');
foreach ($bundles as $bundleName => $bundlePath) {
if (preg_match('/CompanyVendor/', $bundleName, $matches)) {
$routingConfigPath = "#" . $bundleName. $this->path;
try {
$routes->addCollection(
$this->loader->import($routingConfigPath)
);
} catch (FileLoaderImportCircularReferenceException $e) {
throw $e;
} catch (FileLoaderLoadException $e) {
throw $e;
}
}
}
return $routes;
}
}
Maybe someone can help me
I am not familiar with symfony.
There is running Symfony 3.3.9 with Smarty 3.1.27
I want to inject something to the Session Handling, so each time session is started with
new Session() or
$session = $this->container->get('session');
different session values are given
for example
<?php
namespace AppBundle\Components;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
class MDSession extends Session {
private $domain = null;
private $mandant = null;
const DEFAULT_THEME = '_default';
public function __construct(SessionStorageInterface $storage = null,AttributeBagInterface $attributes = null,FlashBagInterface $flashes = null)
{
parent::__construct($storage, $attributes, $flashes);
$this->getDomain();
/**
* check if session is set and the same requested domain given
*/
if(!$this->_get('domain') || $this->_get('domain') != $this->domain)
{
$this->mandant = $this->getMandant();
/**
* set session here
*/
$this->_set('domain', $this->domain);
$this->_set('mandant', $this->mandant['id']);
$this->_set('theme', $this->mandant['theme']);
}
}
public function _set($name=null,$value=null)
{
parent::set($name,$value);
}
public function _get($name)
{
parent::get($name);
}
/**
* HostnameLookups must be set to On in Apache
*/
private function getDomain()
{
$this->domain = strtolower($_SERVER["HTTP_HOST"]);
}
private function getMandant()
{
/**
* do something here
*/
}
}
How to set config.yml or services.yml to get it working ?
at the moment I do it with an EventListener like this.
I hope this is the right way
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class SessionHandler
{
const DEFAULT_THEME = '_default';
const DEFAULT_MANDANT = '1';
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$session = $request->getSession();
$host = $request->getHost();
if(!empty($session->get('mandant')) OR $session->get('host') != $host)
{
//check DB for mandant
//.....
//setting session
$session->set('host', $host);
$session->set('mandant', self::DEFAULT_MANDANT);
$session->set('theme', self::DEFAULT_THEME);
}
if (!$event->isMasterRequest()) {
// don't do anything if it's not the master request
return;
}
// ...
}
}
my class structure is as followed:
myproject
|
-------src (namespace PicoCore;)
|
-----objects (namespace PicoCore\Objects;)
-----tests (namespace PicoCore\Tests;)
I've created composer.json from autoloading:
{
"autoload": {
"psr-0": {
"PicoCore": "src",
"PicoCore\\Objects" : "src/objects",
"PicoCore\\Tests" : "src/tests"
}
}
}
I've created a testing script after installing:
<?php
require_once "../../vendor/autoload.php";
use PicoCore\Objects\User;
$user = new User();
$user->name = "asaf";
echo $user->name;
?>
User Class:
<?php
/**
* Created by PhpStorm.
* User: avivpaz
* Date: 12/25/14
* Time: 12:07 PM
*/
namespace PicoCore\Objects;
class User extends APIUser implements ConvertibleObjects
{
/**
* #var string User's Name
*/
public $name;
/**
* #var string User's Push Id
*/
public $pushId;
/**
* #var UserDevice User's device type
*/
public $userDevice;
/**
* #var double The location latitude
*/
public $latitude;
/**
* #var double The location longitude
*/
public $longitude;
public function __construct()
{
$this->label = USER_LABEL;
}
/**
* init with APIUser
* #param $APIUser APIUser
* #return User type
*/
public static function withAPIUser($APIUser)
{
$user = new User();
$user->label=USER_LABEL;
$user->id = $APIUser->id;
$user->facebookAccessToken = $APIUser->facebookAccessToken;
$user->picoAccessToken = $APIUser->picoAccessToken;
$user->accessTokenExpires = $APIUser->accessTokenExpires;
return $user;
}
public function ConvertObjectToCypherSyntax()
{
return '{id:"' . $this->id . '",name:"' . $this->name . '",picoAccessToken:"' . $this->picoAccessToken . '",accessTokenExpires:"' . $this->accessTokenExpires->getTimestamp() . '",latitude:' . $this->latitude . ',longitude:' . $this->longitude . '}';
}
static public function ConvertNodeToObject($results)
{
$user = new User();
if (is_null($results))
return $user;
$user->id = $results->getProperty('id');
$user->name = $results->getProperty('name');
$user->picoAccessToken = $results->getProperty('picoAccessToken');
$user->latitude = $results->getProperty('latitude');
$user->longitude = $results->getProperty('longitude');
// $user->userDevice = UserDevice::ConvertNodeToObject($results['userDevice']);
if (!$results->getProperty('accessTokenExpires') == "")
$user->accessTokenExpires = getDateTimeFromTimeStamp($results->getProperty('accessTokenExpires'));
return $user;
}
static public function ConvertArrayToObject($array) {
$user = new User();
if (array_key_exists("id", $array))
$user->id = $array["id"];
if (array_key_exists("name", $array))
$user->name = $array["name"];
if (array_key_exists("pico_access_token", $array))
$user->picoAcceessToken = $array["pico_access_token"];
if (array_key_exists("access_token_expires", $array))
$user->accessTokenExpires = getDateTimeFromString($array["access_token_expires"]);
if (array_key_exists("device_type", $array))
$user->deviceType = $array["device_type"];
if (array_key_exists("latitude", $array))
$user->latitude = $array["latitude"];
if (array_key_exists("longitude", $array))
$user->longitude = $array["longitude"];
if (array_key_exists("userDevice", $array))
$user->userDevice = UserDevice::ConvertArrayToObject($array["userDevice"]);
return $user;
}
public function toArray()
{
$user = array();
if (!empty($this->id))
$user["id"] = $this->id;
if (!empty($this->name))
$user["name"] = urldecode($this->name);
if (!empty($this->picoAccessToken))
$user["pico_access_token"] = $this->picoAccessToken;
if (!empty($this->accessTokenExpires))
$user["access_token_expires"] = getMysqlDateTime($this->accessTokenExpires);
if (!empty($this->latitude))
$user["latitude"] = $this->latitude;
if (!empty($this->longitude))
$user["longitude"] = $this->longitude;
if (isset($this->userDevice)) {
$userDevice = $this->userDevice->toArray();
if (!empty($userDevice))
$user["userDevice"] = $userDevice;
}
if (count($user) > 0)
return $user;
return null;
}
}
I get a can't find class exception.. any ideas ?
With PSR-0
In order to use PSR-0, you need to change your structure layout to:
src/
└── PicoCore
├── Objects
│ └── User.php
└── Tests
And in your composer.json you need to add PicoCore namespace:
"psr-0": {
"PicoCore\\": "src"
}
Alternative with PSR-4
If you want to keep your current file system layout, you can use PSR-4 instead of PSR-0. In order to use PSR-4, you need to update composer.json:
"autoload": {
"psr-4": {
"PicoCore\\": "src",
"PicoCore\\Objects\\" : "src/objects",
"PicoCore\\Tests\\" : "src/tests"
}
}
After you made your changes, run composer dumpautoload to regenerate autoload files.
If it's a namespace without class, it's must finish with \\
So :
"autoload": {
"psr-0": {
"PicoCore\\": "src",
"PicoCore\\Objects\\" : "src/objects",
"PicoCore\\Tests\\" : "src/tests"
}
}
and check file autoload
composer/autoload_namespaces.php
see https://getcomposer.org/doc/04-schema.md#psr-0
Is there a way to get the name of the action in a Symfony2 controller?
public function createAction(Request $request, $title) {
// Expected result: create
$name = $this->getActionName();
}
use:
$request->attributes->get('_controller');
// will get yourBundle\Controller\yourController::CreateAction
$params = explode('::',$request->attributes->get('_controller'));
// $params[1] = 'createAction';
$actionName = substr($params[1],0,-6);
// $actionName = 'create';
I found this snippet (here):
$matches = array();
$controller = $this->getRequest()->attributes->get('_controller');
preg_match('/(.*)\\\(.*)Bundle\\\Controller\\\(.*)Controller::(.*)Action/', $controller, $matches);
which seems to be a promising approach. This regexp actually doesn't work. But it won't be hard to fetch the action name by using strstr(). Works!
And returns (see example)
Array
(
[0] => Acme\MyBundle\Controller\MyController::myAction
[1] => Acme
[2] => My
[3] => My
[4] => my
)
If input was Acme\MyBundle\Controller\MyController::myAction.
Now, I am using this with Symfony 2.8, (and Symfony3):
<?php
namespace Company\Bundle\AppBundle\Component\HttpFoundation;
use Symfony\Component\HttpFoundation\Request as BaseRequest;
/**
* Request shortcuts.
*/
class Request extends BaseRequest
{
/**
* Extract the action name.
*
* #return string
*/
public function getActionName()
{
$action = $this->get('_controller');
$action = explode('::', $action);
// use this line if you want to remove the trailing "Action" string
//return isset($action[1]) ? preg_replace('/Action$/', '', $action[1]) : false;
return $action[1];
}
/**
* Extract the controller name (only for the master request).
*
* #return string
*/
public function getControllerName()
{
$controller = $this->get('_controller');
$controller = explode('::', $controller);
$controller = explode('\\', $controller[0]);
// use this line if you want to remove the trailing "Controller" string
//return isset($controller[4]) ? preg_replace('/Controller$/', '', $controller[4]) : false;
return isset($controller[4]) ? $controller[4] : false;
}
}
To use this custom request class, you must "use" it in your web/app*.php controllers:
use Company\Bundle\AppBundle\Component\HttpFoundation\Request;
// ...
$request = Request::createFromGlobals();
// ...
Then in your controller:
class AppController extends Controller
{
/**
* #Route("/", name="home_page")
* #Template("")
*
* #return array
*/
public function homePageAction(Request $request)
{
$controllerName = $request->getControllerName();
$actionName = $request->getActionName();
dump($controllerName, $actionName); die();
// ...
}
Will output:
AppController.php on line 27:
"AppController"
AppController.php on line 27:
"homePageAction"
You can also access these functions through the RequestStack service:
class MyService
{
/**
* #param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
public function myService()
{
$this->controllerName = $this->requestStack->getMasterRequest()->getControllerName();
$this->actionName = $this->requestStack->getMasterRequest()->getActionName();
// ...
}
If you use Controller as a Service than the schema is different:
$request->attributes->get('_controller'); will return "service_id:createAction"
A possible solution for both schemas:
$controller = $request->attributes->get('_controller');
$controller = str_replace('::', ':', $controller);
list($controller, $action) = explode(':', $controller);
In all version of symfony and without $request or container, service or nothing else... , directly in your method
public function myMethod(){
$methodName = __METHOD__;
return $methodName;
}
// return App\Controller\DefaultController::myMethod
public function mySecondMethod(){
$methodName = explode('::', __METHOD__);
return $methodName[1];
}
// return mySecondMethod
I'm wondering how to load a template from it's full path (like FILE constant give).
Actually you have to set a "root" path for template like this :
require_once '/path/to/lib/Twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
'cache' => '/path/to/compilation_cache',
));
And then :
$template = $twig->loadTemplate('index.html');
echo $template->render(array('the' => 'variables', 'go' => 'here'));
I want to call the loadTemplate method with a full path and not the just the name of the file.
How can i do ?
I don't want to create my own loader for such an thing..
Thanks
Just do that:
$loader = new Twig_Loader_Filesystem('/');
So that ->loadTemplate() will load templates relatively to /.
Or if you want to be able to load templates both with relative and absolute path:
$loader = new Twig_Loader_Filesystem(array('/', '/path/to/templates'));
Here is a loader that load an absolute (or not) path given :
<?php
class TwigLoaderAdapter implements Twig_LoaderInterface
{
protected $paths;
protected $cache;
public function __construct()
{
}
public function getSource($name)
{
return file_get_contents($this->findTemplate($name));
}
public function getCacheKey($name)
{
return $this->findTemplate($name);
}
public function isFresh($name, $time)
{
return filemtime($this->findTemplate($name)) < $time;
}
protected function findTemplate($path)
{
if(is_file($path)) {
if (isset($this->cache[$path])) {
return $this->cache[$path];
}
else {
return $this->cache[$path] = $path;
}
}
else {
throw new Twig_Error_Loader(sprintf('Unable to find template "%s".', $path));
}
}
}
?>
Extend the loader better than modify the library:
<?php
/**
* Twig_Loader_File
*/
class Twig_Loader_File extends Twig_Loader_Filesystem
{
protected function findTemplate($name)
{
if(isset($this->cache[$name])) {
return $this->cache[$name];
}
if(is_file($name)) {
$this->cache[$name] = $name;
return $name;
}
return parent::findTemplate($name);
}
}
This works for me (Twig 1.x):
final class UtilTwig
{
/**
* #param string $pathAbsTwig
* #param array $vars
* #return string
* #throws \Twig\Error\LoaderError
* #throws \Twig\Error\RuntimeError
* #throws \Twig\Error\SyntaxError
*/
public static function renderTemplate(string $pathAbsTwig, array $vars)
{
$loader = new Twig_Loader_Filesystem([''], '/');
$twig = new Twig_Environment($loader);
$template = $twig->loadTemplate($pathAbsTwig);
$mailBodyHtml = $template->render($vars);
return $mailBodyHtml;
}
}
Usage:
$htmlBody = UtilTwig::renderTemplate('/absolute/path/to/template.html.twig', [
'some' => 'var',
'foo' => 'bar'
]);
In Symfony's (version 5.4) config add new core path to folder with your templates.
twig:
default_path: '%kernel.project_dir%/templates'
paths:
'%kernel.project_dir%/src/Service/SendEmail/EmailTpl': EmailTpl
Now you can render template.
In controller:
$this->render('#EmailTpl/bobo_reg.html.twig')
In any other place:
$content = $this->container->get('twig')->render('#EmailTpl/bobo_reg.html.twig');