MY PROBLEM
I am tying to make stof/StofDoctrineExtensionsBundle work with symfony3. Therefore instead of using $form->bind as listed in example in stof documentation I tried $form->handleRequest. Unluckily after submitting the form I get the following error:
The file "" does not exist
I would be thankful for you advise what am I doing wrong. Maybe somebody would be so kind and provide me with example of working upload scripts?
MY CODE
My Controller code looks like this:
public function plikAction(Request $request, $dok_id, $plik_id)
{
$em = $this->getDoctrine()->getManager();
if($plik_id == "nowy") $plik = new plik();
/.../
$form = $this->createForm(plikType::class, $plik);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
if($plik_id == "nowy")
{
$em->persist($plik);
$uploadableManager = $this->get('stof_doctrine_extensions.uploadable.manager');
$uploadableManager->markEntityToUpload($plik, $plik->getName());
$em->flush();
$this->get('session')->getFlashBag()->add('success','Dodano plik ');
}
/.../
}
form is build using the following function:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('oznaczenie')
->add('name', FileType::class)
->add('wgraj', SubmitType::class);
}
and my entity class:
/**
* #ORM\Entity
* #ORM\Table
* #Gedmo\Uploadable
*/
class plik
{
/**
* #ORM\Column
* #Gedmo\UploadableFileName
*/
private $name;
/*
* #ORM\Column(type="string", length=100)
* #Gedmo\UploadableFilePath
*/
protected $path;
I am using default configuration as listed here https://symfony.com/doc/master/bundles/StofDoctrineExtensionsBundle/index.html.
By default the value of default_file_path is %kernel.root_dir%/../web/uploads.
To make it working with the default configuration,
create the uploads folder in the web directory of your application:
mkdir web/uploads
And make it writable by setting up the correct permissions depending on your web server user.
Assuming www-data is the web server user, use the following:
chown -R www-data:www-data web/uploads
Or change the directory permissions using chmod (at your own risk):
chmod -R 755 web/uploads
(in case of this commands needs to be executed as root, prefix them with sudo)
Hope this solves your problem.
In my case the Symfony3 error:
The file “” does not exist
was connected with PHP not being able write the file down to temporarily folder due to open_basedir restrictions.
Therefore in any case you see this error in Symfony3 make sure that correct permissions are set to folders and that PHP may write data into it.
Related
I have a rather large Symfony 4.4 project that I recently reopened. Going through the code with PhpStorm 2020.3, adding some new functionality and code cleanup.
I get to a couple of Controllers and I'm getting a "Missing Route" error in PhpStorm. However, the routes do exist when I run php bin/console debug:router.
Is there a cache that I haven't cleared to cause PhpStorm to rescan routes?
Output from: php bin/console debug:router
admin_deviceprofile_index GET ANY ANY /admin/deviceprofile/
admin_deviceprofile_show GET ANY ANY /admin/deviceprofile/{deviceprofile_id}/show
admin_deviceprofile_create GET|POST ANY ANY /admin/deviceprofile/create
admin_deviceprofile_edit GET|POST ANY ANY /admin/deviceprofile/{deviceprofile_id}/edit
admin_deviceprofile_delete DELETE ANY ANY /admin/deviceprofile/{deviceprofile_id}/delete
My snippet of the Controller ...
/**
* #Route("/admin/deviceprofile",
* name="admin_deviceprofile_")
*/
class DeviceProfileController extends AbstractController
{
/**
* Lists all Device Profiles.
* #Route("/",
* name="index",
* methods={"GET"})
* #param Request $request
* #return Response
*/
public function index(Request $request): Response
{ ... }
/**
* Creates a new Device Profile entity.
* #Route("/create",
* name="create",
* methods={"GET", "POST"})
* #param Request $request
* #return Response
*/
public function create(Request $request): Response
{
$profile = new DeviceProfile();
$formProfile = $this->createForm(DeviceProfileType::class, $profile);
$formProfile->handleRequest($request);
if ($formProfile->isSubmitted() && $formProfile->isValid()) {
...
return $this->redirectToRoute('admin_deviceprofile_index');
}
return $this->render(...);
}
}
PhpStorm claims the 'admin_deviceprofile_index' is Missing. However, it is not. Also, this same pattern of having a route for the controller is used elsewhere, yet those routes are fine, the problem appears in just a couple of Controllers.
Also, through debugging this 'problem', I moved the controller route partials to the functions themselves, and PhpStorm still did not see the routes properly.
I have also ran php bin/console cache:clear and have done the PhpStorm: File > Invalidate Caches / Restart to no avail.
Anything I could try to clear this up? I loathe seeing "errors" in the code inspection.
Figured out that if you have a PhpStorm #noinspection tag block and a class-level docblock, it will conflict causing the erroneous "Missing Route" message.
Github issue here
I'm trying to test my RoomRepository with PHPUnit and Symfony 4. I installed symfony/phpunit-bridge using composer. I created a simple entity called Room with one id and name attributs and a repository method to get a Room by its id.
public function get(int $id): ?Room
{
/** #var Room $room */
$room = $this->findOneBy(['id' => $id]);
return $room;
}
My test is quite simple as you can see :
public function testGet(): void
{
/** #var RoomRepository $repository */
$repository = $this->em->getRepository(Room::class);
$room = $repository->get(1);
$this->assertCount(1, $room);
}
I am new with test and I don't know if it's the right way to proceed. I followed the Symfony documentation.
So, when I execute the following command :
./vendor/bin/simple-phpunit
I am getting this error :
Doctrine\DBAL\Exception\ConnectionException: An exception occurred in driver: SQLSTATE[HY000] [2002] No such file or directory
I am pretty sure this is a commun mistake and very easy to fix...
Furthermore, I wrote other simple asserts that worked very well. I don't think it's about PHPUnit configuration.
Here some informations about my env :
PHP 7.1
Symfony4.0.5
PHPUnit 5.7.27
Docker with Laradock (containers : mysql, apache2, workspace)
Thanks guys for reading my post and have a nice day :)
I had the same problem – I just forgot to add the database url to the phpunit.xml.dist file. You have to add:
<phpunit ...>
<php>
...
<env name="DATABASE_URL" value="mysql://username:password#server:port/database" />
...
</php>
...
</phpunit>
Of course with your own credentials instead of the placeholders.
so I've been testing Doctrine queries and other Symfony code and I have to run several commands just to clear Doctrine/Symfony caches. I was searching for the net and came across another command to clear Assetic assets/etc.
From what I've read
php app/console cache:clear
will only clear Symfony cache. it won't include Doctrine and perhaps more.
I know I can create a bash script to clear all my caches but this obviously means I know all the "clear cache" commands. I only found out about the Assetic clear cache/assets by accident. What about those I don't know?
So is there 1 "clear cache" command that can do it for me? This will have to include Symfony/Doctrine/Assetic/Twig and whatever plugins I have installed.
Thanks a lot
What you are looking for is highly dependent on the developer of the bundle that uses the cache. Not even doctrine, that comes with the standard version of symfony has its cache clear command integrated. But what you can do is extend the default symfony command with a listener that runs all the cache clear command you want like this:
<?php
namespace DefaultBundle\Event\Listener;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Process\Process;
class CacheClearListener implements CacheClearerInterface
{
private $environment;
/**
* #return array
*/
private static function getCommands()
{
return array(
'php ./app/console doctrine:cache:clear-metadata --no-debug --flush',
'php ./app/console doctrine:cache:clear-query --no-debug --flush',
'php ./app/console doctrine:cache:clear-result --no-debug --flush'
);
}
public function clear($cacheDir)
{
$output = new ConsoleOutput();
$output->writeln('');
$output->writeln('<info>Clearing Doctrine cache</info>');
foreach (self::getCommands() as $command) {
$command .= ' --env='.$this->environment;
$success = $this->executeCommand($command, $output);
if (!$success) {
$output->writeln(sprintf('<info>An error occurs when running: %s!</info>', $command));
exit(1);
}
}
}
/**
* #param string $command
* #param ConsoleOutput $output
*
* #return bool
*/
private function executeCommand($command, ConsoleOutput $output)
{
$p = new Process($command);
$p->setTimeout(null);
$p->run(
function ($type, $data) use ($output) {
$output->write($data, false, OutputInterface::OUTPUT_RAW);
}
);
if (!$p->isSuccessful()) {
return false;
}
$output->writeln('');
return true;
}
/**
* #param Kernel $kernel
*/
public function setKernel(Kernel $kernel)
{
$this->environment = $kernel->getEnvironment();
}
}
Register the listener like this:
<service id="cache_clear_listener" class="DefaultBundle\Event\Listener\CacheClearListener">
<call method="setKernel">
<argument type="service" id="kernel"/>
</call>
<tag name="kernel.cache_clearer" priority="254" />
</service>
And that is all. Now all you need to do is keep adding your new cache clear command to the getCommands() method. In order to find this commands you can run something like
php app/console | grep cache
to see all available commands that contain the word "cache" in them
After your listener is set, every time you run php app/console cache:clear it will trigger all the command that you listed in the getCommands() method of your listener.
Hope this helps,
Alexandru
My Symfony2 app allows users to upload files. I'd like to users to also be able to download their files.
If I were doing straight PHP, I'd just output the appropriate headers, then output the contents of the file. How would I do this within a Symfony2 controller?
(If you use a hard-coded filename in your answer, that's good enough for me.)
I ended up doing this:
/**
* Serves an uploaded file.
*
* #Route("/{id}/file", name="event_file")
* #Template()
*/
public function fileAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('VNNPressboxBundle:Event')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Event entity.');
}
$headers = array(
'Content-Type' => $entity->getDocument()->getMimeType(),
'Content-Disposition' => 'attachment; filename="'.$entity->getDocument()->getName().'"'
);
$filename = $entity->getDocument()->getUploadRootDir().'/'.$entity->getDocument()->getName();
return new Response(file_get_contents($filename), 200, $headers);
}
Any reason why you do not want to bypass Symfony entirely and just serve the file via your HTTP server (Apache, Nginx, etc)?
Just have the uploaded files dropped somewhere in the document root and let your HTTP server do what it does best.
Update: While the Symfony2 code posted by #Jason Swett will work for 99% of cases - I just wanted to make sure to document the alternative(s). Another way of securing downloads would be to use the mod_secdownload module of Lighttpd. This would be the ideal solution for larger files or files that need to be served quickly with little-as-possible memory usage.
Have a look at the VichUploaderBundle
It will allow you to do this:
/**
* #param integer $assetId
*
* #return Response
*/
public function downloadAssetAction($assetId)
{
if (!$courseAsset = $this->get('crmpicco.repository.course_asset')->findOneById($assetId)) {
throw new NotFoundHttpException('Requested asset (' . $assetId . ') does not exist.');
}
$downloadHandler = $this->get('vich_uploader.download_handler');
return $downloadHandler->downloadObject($courseAsset->getFile(), 'assetFile', null, $courseAsset->getName());
}
When I try to reload my fixtures using
php app/console doctrine:fixtures:load
I'm getting this error:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails (foo_db.Book, CONSTRAINT FK_C29271DD816C6140 FOREIGN KEY (author_id) REFERENCES Author (id))
The error is showed when the status "> purging database" is showed.
This is my code:
class Book{
...
/**
* #ORM\ManyToOne(targetEntity="Author", inversedBy="books")
*/
private $author;
...
}
class Author{
...
/**
* #ORM\OneToMany(targetEntity="Book", mappedBy="author")
*/
private $books;
}
More: my boss has the same code and it doesn't have that error.
Any idea?
sf 2.0.1 (just updated)/ubuntu 10.10.
If I'm guessing correctly, you are using a MySQL database. If yes, then you are facing a bug/problem with the current version of the doctrine-fixtures library for Doctrine2. The problem is that they are using the TRUNCATE command to purge the current database values but this command has problem deleting foreign associations in MySQL.
See this issue and this one on the GitHub repository of the library for more information and workarounds.
In my particular case, I run this command from a script, so to make the command work correctly, I do:
php app/console doctrine:database:drop --force
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load --append
This way, the purging is done by the drop command and appending has the same effect as not appending since the database is empty when the fixtures are loaded.
I must admit I don't know why your boss doesn't have the problem, maybe there is no book associated with an author in his database.
Hope this help.
Regards,
Matt
I've created a simple Event Subscriber class for Symfony 4. All you need to fix the self-referencing foreign keys issue is to add the below class somewhere to your Symfony 4 project.
This subscriber fires before each Symfony CLI command. In case if the command's name is doctrine:fixtures:load, it performs database purge, but doing SET FOREIGN_KEY_CHECKS = 0 first.
This solves the issue without any other modification.
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ConsoleCommandEventSubscriber implements EventSubscriberInterface
{
/**
* #var EntityManagerInterface
*/
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public static function getSubscribedEvents()
{
return [
ConsoleEvents::COMMAND => 'onCommand',
];
}
public function onCommand(ConsoleCommandEvent $event)
{
if ($event->getCommand()->getName() === 'doctrine:fixtures:load') {
$this->runCustomTruncate();
}
}
private function runCustomTruncate()
{
$connection = $this->entityManager->getConnection();
$connection->exec('SET FOREIGN_KEY_CHECKS = 0');
$purger = new ORMPurger($this->entityManager);
$purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
$purger->purge();
$connection->exec('SET FOREIGN_KEY_CHECKS = 1');
}
}
Add to your composer.json new section script
"scripts": {
"load-fixtures": [
"bin/console doctrine:database:drop --if-exists --force",
"bin/console doctrine:database:create",
"bin/console doctrine:mi:m",
"bin/console doctrine:fixtures:load"
]
}
Then you can run composer install && composer load-fixtures