Dependency Injecting the Laravel Cache System - php

Is there anyway to inject the laravel cache system and have access to the increment method.
\Cache::increment('key');
So far I have the following, but no increase method.
/**
* #var Cache\Repository
*/
protected $cache;
/**
* RateLimiter constructor.
*
* #param Cache\Repository $cache
*/
public function __construct(Cache\Repository $cache)
{
$this->cache = $cache;
}
I've tried injecting Cache\Store but that is not instantiable
EDIT:
use Illuminate\Contracts\Cache; is not show in above extract, but it's there.
Any suggestions???

According to the official docs the underline class of the Cache facade is Illuminate\Cache\Repository, not Cache\Repository

Related

Is it possible to use redis or an alternative cache with HTMLPurifier?

Using HTML Purifier (ezyang/htmlpurifier) or specifically (stevebauman/purify) for Laravel 7 (powered by the former), is it possible to use an alternative cache than the filesystem?
The docs imply that you can use the FS, or null (not recommended) but also that the FS is just an implementation. Are other implementations possible (ideally Redis), and how would they be configured?
There are currently no official caches in the HTML Purifier library other than "Serializer". That said, you can write your own extension of HTMLPurifier_DefinitionCache.
To be able to load your custom cache, you would have to register your implementation with DefinitionCacheFactory. As I understand it, this should work:
...
$factory = HTMLPurifier_DefinitionCacheFactory::instance();
$factory->register('YourImplName', 'YourFullClassName');
$config->set('Cache.DefinitionImpl', 'YourImplName');
...
You can see which methods you would need to implement in DefinitionCache.php, which you'll need to extend (class YourFullClassName extends HTMLPurifier_DefinitionCache). In the spirit of not leaving most of the answer accessible only in a link, here are the abstract methods of the class that you definitely have to implement:
/**
* Adds a definition object to the cache
* #param HTMLPurifier_Definition $def
* #param HTMLPurifier_Config $config
*/
abstract public function add($def, $config);
/**
* Unconditionally saves a definition object to the cache
* #param HTMLPurifier_Definition $def
* #param HTMLPurifier_Config $config
*/
abstract public function set($def, $config);
/**
* Replace an object in the cache
* #param HTMLPurifier_Definition $def
* #param HTMLPurifier_Config $config
*/
abstract public function replace($def, $config);
/**
* Retrieves a definition object from the cache
* #param HTMLPurifier_Config $config
*/
abstract public function get($config);
/**
* Removes a definition object to the cache
* #param HTMLPurifier_Config $config
*/
abstract public function remove($config);
/**
* Clears all objects from cache
* #param HTMLPurifier_Config $config
*/
abstract public function flush($config);
/**
* Clears all expired (older version or revision) objects from cache
* #note Be careful implementing this method as flush. Flush must
* not interfere with other Definition types, and cleanup()
* should not be repeatedly called by userland code.
* #param HTMLPurifier_Config $config
*/
abstract public function cleanup($config);
There are some other methods in that class that you can override if you find a need to override them, e.g. generateKey($config) or isOld($key, $config).
I hope that helps!

How to subscribe to the DataTableFactory service?

I am trying to use DataTablesBundle in Symfony 4.2.
There is very good manual and starter however it is used with extends Controller class. But I am trying to use it with AbstractController
class.
So I have such issue:
Service "Omines\DataTablesBundle\DataTableFactory" not found: even
though it exists in the app's container, the container inside
"App\Controller\StaffController" is a smaller service locator that
only knows about the "doctrine", "form.factory", "http_kernel",
"parameter_bag", "request_stack", "router",
"security.authorization_checker", "security.csrf.token_manager",
"security.token_storage", "serializer", "session" and "twig" services.
Try using dependency injection instead
I have found a solution however I have just started with Symfony so I haven't really understood what it is about:
https://github.com/omines/datatables-bundle/commit/cd9b93eac9ef4fd3c1459305c71ca6e2ac0c444e
If using AbstractController instead, which is currently
recommended practice, ensure you subscribe to the
DataTableFactory service yourself. Alternatively you can
bypass the convenience trait and inject the service via regular
constructor injection
How to subscribe to the DataTableFactory service?
And what does the alternative "bypass the convenience trait and inject the service" mean?
I don't know how to subscribe to a service, but here is how to inject it.
Add a constructor to your controller and inject the DataTableFactory:
//use Omines\DataTablesBundle\DataTableFactory;
private $factory;
public function __construct(
DataTableFactory $factory
) {
$this->factory = $factory;
}
/**
* Creates and returns a basic DataTable instance.
*
* #param array $options Options to be passed
* #return DataTable
*/
protected function createDataTable(array $options = [])
{
return $this->factory->create($options);
}
/**
* Creates and returns a DataTable based upon a registered DataTableType or an FQCN.
*
* #param string $type FQCN or service name
* #param array $typeOptions Type-specific options to be considered
* #param array $options Options to be passed
* #return DataTable
*/
protected function createDataTableFromType($type, array $typeOptions = [], array $options = [])
{
return $this->factory->createFromType($type, $typeOptions, $options);
}
Then you can use it like this:
$this->createDateTable();

Laravel: dependency injection in commands

Is dependency injection of a custom class in a command possible?
I'm trying this:
<?php
namespace vendor\package\Commands;
use Illuminate\Console\Command;
use vendor\package\Models\Log;
use vendor\package\Updates\UpdateStatistics;
class UpdatePublishmentStats extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'vendorname:updatePublishmentStats';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Updates Twitter followers & Facebook page likes';
/**
* Contact implementation
* #var vendor\package\Update\UpdateStatistics
*/
protected $stats;
/**
* Create a new command instance.
*
* #return void
*/
public function __construct(
Log $log,
UpdateStatistics $stats
) {
parent::__construct();
$this->log = $log;
$this->stats = $stats;
}
But when I try to do this:
public function handle()
{
$this->stats->updateFbStats();
}
I suddenly get Segmentation fault: 11
When I delete the use vendor\package\Updates\UpdateStatistics; part, I don't get that error.
So what am I doing wrong here? Is it not possible to use dependency injection in a command?
You can inject any service in the handle method:
Note that we are able to inject any dependencies we need into the command's handle method.
Source: https://laravel.com/docs/5.8/artisan#command-structure
According to the Command Structure section of 5.2 documentation (https://laravel.com/docs/5.2/artisan#writing-commands):
"Note that we are able to inject any dependencies we need into the command's constructor. The Laravel service container will automatically inject all dependencies type-hinted in the constructor."
So I think you're good there, as far as the capability being present and available.
As for getting it to work, for me the segfault points to something wrong with the UpdateStats class, how it's referenced in the service container, or how its being resolved from the service container.
I don't have a definitive answer, but what I would do is try another class and see if I could localize the issue to this particular class, or if the problem happens with others, and then try and debug from there.
Also, if you just can't get that to work, the app() function will resolve items from the service container when you want (although looking through the 5.2 docs I don't see it anymore, so it may be deprecated - I do see $this->app->make() however).
This may work for you if nothing else does:
public function __construct(
Log $log,
) {
parent::__construct();
$this->log = $log;
$this->stats = app(UpdateStatistics::class);
}
My guess is, however, that you will get a segfault with this as well, as it should try resolving the same class the same way. If you do, then at least the error is a little clearer, and unrelated to auto-injecting feature.
Hope that at least helps a little.
Update on the app() function
So the app() function does not appear to be documented, but I have 5.2 installed right now and the helpers.php file in Illuminate/Foundation definitely has the function:
if (! function_exists('app')) {
/**
* Get the available container instance.
*
* #param string $make
* #param array $parameters
* #return mixed|\Illuminate\Foundation\Application
*/
function app($make = null, $parameters = [])
{
if (is_null($make)) {
return Container::getInstance();
}
return Container::getInstance()->make($make, $parameters);
}
}
Unfortunately the API documentation doesn't include any of the helper functions, but the current master, 5.2, and 5.3 versions of the file on Github all have the function:
https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/helpers.php#L91
https://github.com/laravel/framework/blob/5.3/src/Illuminate/Foundation/helpers.php#L91
https://github.com/laravel/framework/blob/5.2/src/Illuminate/Foundation/helpers.php#L91

Injecting dependencies using annotations in Symfony

I come from a Spring/Java background and i'm learning Symfony/PHP. It's amazingly similar and i love it.
In Spring we can #Autowire dependencies. What is the equivalent of that in Symfony? I want to inject my dependencies using annotations. And i dont want to specify that in an xml or yml.
For example:
class foo {
/**
* #Inject \ABC\XYZ\Dependency
*/
private $dependency;
public function abc(){
$dependency->bar();
}
};
Also (now this just got on my mind now), is it possible to do something like this. Using annotations, declaring a name and scope for the service:
/**
* #Service("someService")
* #Scope("session / request / ..")
*/
class foo {
/**
* #Inject \ABC\XYZ\Dependency
*/
private $dependency;
public function abc(){
$dependency->bar();
}
};
Autowiring will be available as of Symfony 2.8: http://symfony.com/blog/new-in-symfony-2-8-service-auto-wiring

Cached user class vs seperate class holding necessary cached fields

I need to cache some info about a user who is logged in (such as security groups, name, username, etc.)
Currently I have a separate class to achieve just this, lets call it CurrentUserHelper. Given a user object, it will cache the appropriate data and save store info in the $_SESSION variable.
The issue is I'm finding a bunch of classes relying just on CurrentUserHelper because they only need a couple of common fields. In fact, most of the functions have the same name as my User class. There's a couple of functions in CurrentUserHelper, such as getSecurityGroupsNames(), that contains a cache of all security group names, but there is no reason this function name could not be in the user class also.
Instead, should I create a CachedUser class and pass this around? This class can extend User, but then I can override getName(), getSecurityGroups(), etc, and returned the cached data, and not preform db requests to get the data.
The downside of passing around a CachedUser object is that this kind of hides the fact the data isn't really up to date if a constructor/function is accepting a type User. I also need to find way to handle merging the entity with Doctrine 2, and making sure entities associating themselves with a CachedUser won't break. If I decide to cache some temporary data (such as # of page views since logged in), this property shouldn't be part of the User class, it's more about the current user's session.
If I continue using the CurrentUserHelper class, maybe I should create an interface and have both CurrentUserHelper and User for the common functionality the two classes would share?
Preface: Extension isn't the best way for these sorts of things.. I'm sure you've heard composition over inheritance shouted at you over and over again. In fact, you can even gain inheritance without using extends!
This sounds like a good use-case for the decorator pattern. Basically, you wrap your existing object with another one that implements the same interface, so it has the same methods as the inner object, but this object's method adds the extra stuff around the method call to the inner object, like caching, for example.
Imagine you have a UserRepository:
/**
* Represents an object capable of providing a user from persistence
*/
interface UserProvider
{
/**
* #param int $id
*
* #return User
*/
public function findUser($id);
}
/**
* Our object that already does the stuff we want to do, without caching
*/
class UserRepository implements UserProvider
{
/**
* #var DbAbstraction
*/
protected $db;
/**
* #var UserMapper
*/
protected $mapper;
/**
* #param DbAbstraction $db
* #param UserMapper $mapper
*/
public function __construct(DbAbstraction $db, UserMapper $mapper)
{
$this->db = $db;
$this->mapper = $mapper;
}
/**
* {#inheritDoc}
*/
public function findUser($id)
{
$data = $this->db->find(['id' => $id]);
/** Data mapper pattern - map data to the User object **/
$user = $this->mapper->map($data);
return $user;
}
}
The above is a really simple example. It'll retrieve the user data from it's persistence (a database, filesystem, whatever), map that data to an actual User object, then return it.
Great, so now we want to add caching. Where should we do this, within the UserRepository? No, because it's not the responsibility of the repository to perform caching, even if you Dependency Inject a caching object (or even a logger!).. this is where the decorator pattern would come in useful.
/**
* Decorates the UserRepository to provide caching
*/
class CachedUserRepository implements UserProvider
{
/**
* #var UserRepository
*/
protected $repo;
/**
* #var CachingImpl
*/
protected $cache;
/**
* #param UserRepository $repo
*/
public function __construct(UserRepository $repo, CachingImpl $cache)
{
$this->repo = $repo;
$this->cache = $cache;
}
/**
* {#inheritDoc}
*
* So, because this class also implements UserProvider, it has to
* have the same method in the interface. We FORWARD the call to
* the ACTUAL user provider, but put caching AROUND it...
*/
public function findUser($id)
{
/** Has this been cached? **/
if ($this->cache->hasKey($id))
{
/**
* Returns your user object, or maps data or whatever
*/
return $this->cache->get($id);
}
/** Hasn't been cached, forward the call to our user repository **/
$user = $this->repo->findUser($id);
/** Store the user in the cache for next time **/
$this->cache->add($id, $user);
return $user;
}
}
Very simply, we've wrapped the original object and method call with some additional caching functionality. The cool thing about this is that, not only can you switch out this cached version for the non-cached version at any time (because they both rely on the same interface), but you can remove the caching completely as a result, just by changing how you instantiate this object (you could take a look at the factory pattern for that, and even decide which factory (abstract factory?) depending on a configuration variable).

Categories