Delete file from a folder in symfony 4 - php

I have a controller with a supprimer action.
I can add files and delete them from the database.
As I followed the Symfony doc to create an uploader file, I also created in my services.yml this route
parameters:
repertoire_soumissions: '%kernel.project_dir%/public/uploads/LettresSoumissios'
My problem
When I delete my file with my supprimer action, it's fine it deletes it in my database. But not in my folder /public/uploads/LettresSoumissions. I tried to find a way to be able to delete them in my folder too, but couldn't succeed it.
I tried also with a Filesystem() to remove them, but I've must have written it badly.
Here is my action in my controller class
/**
* #Route("admin/soumission/{id}/supprimer", name="supprimer_soumission")
*/
public function supprimerSoumission(Soumission $soumission, ObjectManager $manager){
$lettresoumission= $soumission->getLettreSoumission();
$filesystem = new Filesystem();
$path='%kernel.project_dir%/public/uploads/LettresSoumissios/'.$lettresoumission;
$filesystem->remove($path);
$manager->remove($soumission);
$manager->flush();
$this->addFlash('success','Soumission supprimer !!');
return $this->redirectToRoute('soumission');
}

Could it be due to a mispelling in the path name?
$path='%kernel.project_dir%/public/uploads/LettresSoumissioNs/'.$lettresoumission;
Missing a N letter.

Your problem is this line:
$path='%kernel.project_dir%/public/uploads/LettresSoumissios/'.$lettresoumission;
The parameter above is simply a string with value:
%kernel.project_dir%
You need a way to retrive the value of the parameter.
A clean way would be to inject the parameter value in the controller.
Define your Controller as a service in your service.yaml:
Namespace\NameOfTheController:
arguments:
- '%kernel.project_dir%'
tags: [controller.service_arguments]
Inject the value in the Constructor of your Controller:
private $kernelRoot;
public function __construct(string $kernelRoot)
{
$this->kernelRoot = $kernelRoot;
}
Now change your code-line to:
$path=$this->kernelRoot.'/public/uploads/LettresSoumissios/'.$lettresoumission;
to clarify:
You said:
I also created in my services.yml this route
parameters:
repertoire_soumissions: '%kernel.project_dir%/public/uploads/LettresSoumissios'
This is no service or route declaration, this is just a parameter => value mapping.

Related

Routing order symfony 4

I want to have a url with a wildcard at the end site.com/{username} after trying to match url's like site.com/photos and site.com/blog. I'm using annotations and have two controllers.
I found an answer here Ordering of routes using annotations
But the folder structure is different in version 4 and in the answer they are using YAML while I'm using annotations, so I don't fully understand where to put what.
Video Controller
/**
* #Route("/videos", name="videos")
*/
public function index()
{
// Show video homepage
}
User Controller
/**
* #Route("/{username}", name="profile")
*/
public function index()
{
// Hello {username} !
}
In this order, site.com/videos reaches User controller instead of videos. Do I have to switch to manually putting all URL structures in yaml format or is there a way to set priority in annotations?
So far the only method I found was to create a controller starting with the letter "Z", and putting the action/route in there, that seems to run the route last.
The question you linked to is actually very relevant. You are asking just the same as the other guy:
But how can you do this if you define your routes as annotations in your controllers? Is there any way to specify the ordering of this routes in this case?
In Symfony 4, your config/routes.yaml is probably empty and config/routes/annotations.yaml probably like this:
controllers:
resource: ../../src/Controller/
type: annotation
You can replace the above YAML with this – notice that the order does matter:
Video:
resource: App\Controller\VideoController
type: annotation
User:
resource: App\Controller\UserController
type: annotation
Then site.com/videos reaches the video controller first.
You have to define your routes with yml/xml to be able to fully configure their order.
If you really want to use annotation you could add a prefix like user-:
/**
* #Route("/user-{username}", name="profile")
*/
public function index()
{
// Hello {username} !
}

symfony 3 routing with annotations + locale listener - how to avoid duplicate "requirements" for every route?

Clean setup of Symfony 3 framework, added locale listener from here:
http://symfony.com/doc/current/cookbook/session/locale_sticky_session.html
Example action code:
/**
* #Route("/foo/")
* #Route("/{_locale}/foo/", name="foo", requirements={"_locale"="en|ru|tk"})
*/
public function fooAction(Request $request)
{
return new Response('true');
}
This syntax has to be repeated for every action. Is there a way to make it less verbose without using a Bundle? I'd like the requirements portion to reside in a config somewhere, if possible.
Ideally, I would like to move the defaults={"_locale"="en"}, requirements={"_locale"="%allowed_locales%"} part inside the Locale Listener, but from what I've tried, it seems the listener is called after the route has been matched, and so that is not possible, which is really a shame.
Yes, check out How to Use Service Container Parameters in your Routes which is linked from The Locale and the URL in the Symfony Translations documentation, and states:
Read How to Use Service Container Parameters in your Routes to learn how to avoid hardcoding the _locale requirement in all your routes.
You can essentially set those routes in a global parameter like so:
# app/config/config.yml
parameters:
app.locales: en|ru|tk
Then in your route annotations do the following:
/**
* #Route("/foo/")
* #Route("/{_locale}/foo/", name="foo", requirements={"_locale"="%app.locales%"})
*/
public function fooAction(Request $request)
{
return new Response('true');
}
I'm not sure why the documentation only shows that for defining routes in YAML / XML / PHP but it should work just the same using annotations.

How to use relative paths in symfony2?

This is going to be a short, nevertheless complicated question. Let me try and explain what I am trying to accomplish.
I've got a config file config.yml
# src/Company/HappyBundle/Resources/config/config.yml
company_happy:
import:
attachments_path: "#CompanyHappyBundle/Resources/public/attachments"
I'm trying to get the attachments_path parameter in a Command. I do this using the following line:
$this->container->getParameter('company_happy.import.attachments_path');
Now, how can I convert #CompannyHappyBundle to the actual path?
Update
If you have any information on better ways to do this, this is always welcome. What I'm trying to do is to save attachments to the bundle's public folder.
You don't need to store your attachments at the bundle's home directory. Also you have wrong definition for parameter. All parameters in Service container must be located under parameters section.
As you can see here you need to create Form with file field. Then fill this form with Request data and then use move() method upon it to move file in any location you need. The most popular place for it - web/uploads directory.
public function uploadAction()
{
$form = $this->createFormBuilder()
->add('attachment', 'file')
->getForm();
if ($form->isValid()) {
$dir = $this->container->getParameter('kernel.root_dir').'/../web/uploads';
$someNewFilename = '...';
$form['attachment']->getData()->move($dir, $someNewFilename);
// ...
}
// ...
}
Set a value in your parameters.yml as following:
# parameters.yml
parameters:
company_happy.import.attachments_path: "#CompanyHappyBundle/Resources/public/attachments"
Then call it the same in your controller as you currently are.

Laravel get url's route name [duplicate]

In Laravel, we can get route name from current URL via this:
Route::currentRouteName()
But, how can we get the route name from a specific given URL?
Thank you.
A very easy way to do it Laravel 5.2
app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1'))->getName()
It outputs my Route name like this slug.posts.show
Update: For method like POST, PUT or DELETE you can do like this
app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1', 'POST'))->getName()//reference https://github.com/symfony/http-foundation/blob/master/Request.php#L309
Also when you run app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1', 'POST')) this will return Illuminate\Routing\Route instance where you can call multiple useful public methods like getAction, getValidators etc. Check the source https://github.com/illuminate/routing/blob/master/Route.php for more details.
None of the solutions above worked for me.
This is the correct way to match a route with the URI:
$url = 'url-to-match/some-parameter';
$route = collect(\Route::getRoutes())->first(function($route) use($url){
return $route->matches(request()->create($url));
});
The other solutions perform bindings to the container and can screw up your routes...
I don't think this can be done with out-of-the-box Laravel. Also remember that not all routes in Laravel are named, so you probably want to retrieve the route object, not the route name.
One possible solution would be to extend the default \Iluminate\Routing\Router class and add a public method to your custom class that uses the protected Router::findRoute(Request $request) method.
A simplified example:
class MyRouter extends \Illuminate\Routing\Router {
public function resolveRouteFromUrl($url) {
return $this->findRoute(\Illuminate\Http\Request::create($url));
}
}
This should return the route that matches the URL you specified, but I haven't actually tested this.
Note that if you want this new custom router to replace the built-in one, you will likely have to also create a new ServiceProvider to register your new class into the IoC container instead of the default one.
You could adapt the ServiceProvider in the code below to your needs:
https://github.com/jasonlewis/enhanced-router
Otherwise if you just want to manually instantiate your custom router in your code as needed, you'd have to do something like:
$myRouter = new MyRouter(new \Illuminate\Events\Dispatcher());
$route = $myRouter->resolveRouteFromUrl('/your/url/here');
It can be done without extending the default \Iluminate\Routing\Router class.
Route::dispatchToRoute(Request::create('/your/url/here'));
$route = Route::currentRouteName();
If you call Route::currentRouteName() after dispatchToRoute call, it will return current route name of dispatched request.

Laravel get route name from given URL

In Laravel, we can get route name from current URL via this:
Route::currentRouteName()
But, how can we get the route name from a specific given URL?
Thank you.
A very easy way to do it Laravel 5.2
app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1'))->getName()
It outputs my Route name like this slug.posts.show
Update: For method like POST, PUT or DELETE you can do like this
app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1', 'POST'))->getName()//reference https://github.com/symfony/http-foundation/blob/master/Request.php#L309
Also when you run app('router')->getRoutes()->match(app('request')->create('/qqq/posts/68/u1', 'POST')) this will return Illuminate\Routing\Route instance where you can call multiple useful public methods like getAction, getValidators etc. Check the source https://github.com/illuminate/routing/blob/master/Route.php for more details.
None of the solutions above worked for me.
This is the correct way to match a route with the URI:
$url = 'url-to-match/some-parameter';
$route = collect(\Route::getRoutes())->first(function($route) use($url){
return $route->matches(request()->create($url));
});
The other solutions perform bindings to the container and can screw up your routes...
I don't think this can be done with out-of-the-box Laravel. Also remember that not all routes in Laravel are named, so you probably want to retrieve the route object, not the route name.
One possible solution would be to extend the default \Iluminate\Routing\Router class and add a public method to your custom class that uses the protected Router::findRoute(Request $request) method.
A simplified example:
class MyRouter extends \Illuminate\Routing\Router {
public function resolveRouteFromUrl($url) {
return $this->findRoute(\Illuminate\Http\Request::create($url));
}
}
This should return the route that matches the URL you specified, but I haven't actually tested this.
Note that if you want this new custom router to replace the built-in one, you will likely have to also create a new ServiceProvider to register your new class into the IoC container instead of the default one.
You could adapt the ServiceProvider in the code below to your needs:
https://github.com/jasonlewis/enhanced-router
Otherwise if you just want to manually instantiate your custom router in your code as needed, you'd have to do something like:
$myRouter = new MyRouter(new \Illuminate\Events\Dispatcher());
$route = $myRouter->resolveRouteFromUrl('/your/url/here');
It can be done without extending the default \Iluminate\Routing\Router class.
Route::dispatchToRoute(Request::create('/your/url/here'));
$route = Route::currentRouteName();
If you call Route::currentRouteName() after dispatchToRoute call, it will return current route name of dispatched request.

Categories