Is there any possibility to enable Doctrine's Query Caching for a given application?
Tried in Configuration.class.php, but without luck.
You can add your:
public function configureDoctrine(Doctrine_Manager $manager)
{
// Doctrine_Cache_Apc in the example
$manager->setAttribute(Doctrine::ATTR_QUERY_CACHE, new Doctrine_Cache_Apc());
}
to your:
/<project_path>/apps/<app_name>/config/<app_name>Configuration.class.php
Related
I'm using Doctrine inside Symfony and Here is what I do in a test method:
public function it_should_publish_video()
{
// fixture setup
$entityManager = static::bootKernel()->getContainer()->get('doctrine')->getManager();
// video builder constructs a new video (new Video('title','date')) but doesn't persist it.
$video = VideoBuilder::new()->make();
$entityManager->persist($video);
$entityManager->flush();
$videoService = new VideoService($entityManager);
// excerice
$videoService->publish($video->getId());
// verification
$publishedVideo = $entityManager->find($video->getId());
$this->assertEquals($publishedVideo->getStatus(), 'published');
}
and here is my production code:
public function publish($videoId)
{
$video = $this->entityManager->getRepository(Video::class)->find($videoId);
// changes the status
$video->publish();
// but I don't persist and flush it
}
I'm wondering why my test gets passed while I'm not persisting changes.
I think the find() is caching the result. I've searched a lot, there are suggestions about using clear() before find() or using refresh() after find() or using findBy() instead of find(). I don't want to change my production code for the sake of testing.
I've read the documentation but I couldn't find a place to disable this kind of cache.
I would like to use the PUT method for creating resources. They are identified by an UUID, and since it is possible to create UUIDs on the client side, I would like to enable the following behaviour:
on PUT /api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881 if this resource exists, update it
on PUT /api/myresource/4dc6efae-1edd-4f46-b2fe-f00c968fd881 if this resource does not exist, create it
It's possible to achieve this by implementing an ItemDataProviderInterface / RestrictedDataProviderInterface.
However, my resource is actually a subresource, so let's say I want to create a new Book which references an existing Author.
My constructor looks like this:
/**
* Book constructor
*/
public function __construct(Author $author, string $uuid) {
$this->author = $author;
$this->id = $uuid;
}
But I don't know how to access the Author entity (provided in the request body) from my BookItemProvider.
Any ideas?
In API Platform many things that should occur on item creation is based on the kind of request it is. It would be complicated to change.
Here are 2 possibilities to make what you want.
First, you may consider to do a custom route and use your own logic. If you do it you will probably be happy to know that using the option _api_resource_class on your custom route will enable some listeners of APIPlaform and avoid you some work.
The second solution, if you need global behavior for example, is to override API Platform. Your main problem for this is the ReadListener of ApiPlatform that will throw an exception if it can't found your resource. This code may not work but here is the idea of how to override this behavior:
class CustomReadListener
{
private $decoratedListener;
public function __construct($decoratedListener)
{
$this->decoratedListener = $decoratedListener;
}
public function onKernelRequest(GetResponseEvent $event)
{
try {
$this->decoratedListener->onKernelRequest($event);
} catch (NotFoundHttpException $e) {
// Don't forget to throw the exception if the http method isn't PUT
// else you're gonna break the 404 errors
$request = $event->getRequest();
if (Request::METHOD_PUT !== $request->getMethod()) {
throw $e;
}
// 2 solutions here:
// 1st is doing nothing except add the id inside request data
// so the deserializer listener will be able to build your object
// 2nd is to build the object, here is a possible implementation
// The resource class is stored in this property
$resourceClass = $request->attributes->get('_api_resource_class');
// You may want to use a factory? Do your magic.
$request->attributes->set('data', new $resourceClass());
}
}
}
And you need to specify a configuration to declare your class as service decorator:
services:
CustomReadListener:
decorate: api_platform.listener.request.read
arguments:
- "#CustomReadListener.inner"
Hope it helps. :)
More information:
Information about event dispatcher and kernel events: http://symfony.com/doc/current/components/event_dispatcher.html
ApiPlatform custom operation: https://api-platform.com/docs/core/operations#creating-custom-operations-and-controllers
Symfony service decoration: https://symfony.com/doc/current/service_container/service_decoration.html
I want to share a variable in all views but i'm not sure if this is the right way to do it? I have made a service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Worktype;
class ShareWorktypesInViewsProwider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$worktypes = Worktype::all();
view()->share('worktypes', $worktypes);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
but i still get an error in my view. Do i need to register my service provider or it should work out of the box?
Firstly, for such a small piece of code I wouldn't worry about creating a brand new service provider. I would just add the above to your AppServiceProvider. Also, you code inline the above as well:
view()->share('worktypes', Worktype::all());
As for registering a provider. Literally all you have to do is go to config/app.php, find the providers array and add your provider to it.
In your can you would add:
App\Providers\ShareWorktypesInViewsProwider::class,
The documentation for it:
https://laravel.com/docs/5.3/providers#registering-providers
Hope this helps!
A more recent update on this. While #Rwd solution works great, you may run into difficulties as the service provider is run every single request.
As a result, you'll end up requesting Worktype from the database regardless of whether you're on a view, etc.
The best way to achieve this now is by using Laravel View composers.
By adding the below into your service provider, you'll only call the Worktype::all() when needed within a view.
view()->composer('*', function($view) {
$view->with(['worktypes' => Worktype::all()]);
});
Although make sure to use some caching otherwise it'll get called for every view!
I want a variable bound to the application scope, (in java that would be application scope).
I thought service should be the thing to use in order to reach my goal.
I created a service test
<?php
namespace Acme\MyBundle\Service;
class test {
public $count;
public function __construct() {
$this->count = 0;
}
public function addCount() {
$this->count++;
}
}
which I declared in services.yml
acme.my.service.test:
class: Acme\MyBundle\Service\test
I call it in my controller
public function testAction() {
$this->get('acme.my.service.test')->addCount();
return $this->render('AcmeMyBundle:Test:test.html.twig');
}
But when I retrieve it in my twig, the value is 1, no matter how much I refresh or go with multiple session on the url bound to my testAction.
=> It means that constructor is called each time.
So is that the right way to do? I thought services were created once and reused then, but I may be mistaken.
Could you please enlighten me?
Thank you,
copndz
I found what I was looking for, APC caching system.
Easy to use and integrated to doctrine common.
How to cache in Symfony 2?
http://docs.doctrine-project.org/en/latest/reference/caching.html
It's a bit tedious writing the whole path to the Entity when calling getRepository(). Especially in Symfony2 where it would be Acme\FooBundle\BarEntity. Is it possible to make it so you only have to specify the Entity name?
I'm adding a static method to my entities like this:
public static function getEntityName()
{
return get_called_class();
}
then
use Acme\FooBundle\BarEntity;
$repo = $em->getRepository(BarEntity::getEntityName());
You can write ->getRepository('FooBundle:BarEntity')