Confused by Symfony's file upload documentation - symfony

The last section of Symfony 2.1's file upload documentation, which provides instructions on how to use the database id of a document as its filename, rewrites the getAbsolutePath() function:
public function getAbsolutePath()
{
return null === $this->path
? null
: $this->getUploadRootDir().'/'.$this->id.'.'.$this->path;
}
I am confused. It seems like the path property is no longer storing the path, but the extension. What's going on here?
I am trying to alter the class to put uploads in a uploads/YYYY/MM folder, and am not sure where I should be putting that. My inclination is to store the /YYYY/MM part in the path property, but again it seems like it's storing the extension.

Why is extension in the path property is explained at the top of the code block:
If you want to use the id as the name of the file, the implementation is slightly different as you need to save the extension under the path property, instead of the actual filename
As for where to put uploads/YYYY/MM - purely by looking at the documentation example I'd assume that it should go into the Document::getUploadRootDir() method.
Assuming that you're storing a createdAt field to track when Document was created, the method could look like this:
public function getUploadRootDir()
{
return sprintf('uploads/%s/%s', $this->createdAt->format('y'), $this->createdAt->format('m'));
}

Related

in ASP.NET core (.NET5) how can i write logs for each request on separate files? Using Serilog or other

I'm new to .NET and to webservice development, so i'm not exactly sure how to implement the requirement i have.
My webservice gets a POST request with some data, which i need to
process to generate a pdf file: name_YYYYMMDDHHmmss.pdf.
For monitoring this i want to have a separate logfile for each request, named like the output file: name_YYYYMMDDHHmmss.log
I would like to avoid passing a config object into every class/function in which i need to add stuff to the log file
I've managed to install Serilog and it works for what i need, but not when i get concurrent requests. I'm also not exactly sure how simultaneous requests are handled in .NET (i have no thread specific code written so far), but as far as i can tell, when i change Global Logger file name, that object is shared across all threads so all of them write to the same file.
I've looked at a bunch of solutions, but i haven't managed to find nothing that suits this, and it seems most people have everything into 1 file...
Is there any clue or tips you can give me? I'm open to using something other than Serilog.
One way to have dynamic file names based on a specific context is by using the Serilog.Sinks.Map and then, via a middleware in the request pipeline, you can add a property to the log context that drives the file name to be used when writing to the log.
Examples of similar usage of Serilog.Sinks.Map to decide which file name to use at run-time:
Serilog - can not log to multiple files based on property
In Serilog dynamically changing log file path?
The best solution that I found to this problem was using Serilog.Sinks.Map. I configured my Logger something like this:
Log.Logger = new LoggerConfiguration()
.WriteTo.Map("Name", "Default", (name, wt) => {
var fileName = name == "Default" ? "log" : $"{log-{name}}"
wt.File($"./{fileName}-.txt");
}).CreateLogger();
Then on my controller, on each method where I needed this feature, I enclosed all the instructions inside a LongContext like this:
[HttpGet]
public IHttpActionResult Get() {
using (LogContext.PushProperty("Name", "theFileName") {
// ...
_myService.Method1();
// ...
}
}
public class MyService : IMyService {
// ...
public void Method1() {
// ...
Log.Information("This is what happened at this point…");
// ...
}
// ...
}
So all the Log's inside will use that context and it will write on a different file with the name you set for that context without having to modify any Log.Information/Error/Warning/etc that you already have on your code.
This is the ugly part... you have to define a context on a root place in order to make those Logs write on a different file. So for a controller method, the first thing you have to do is to enclose all with a LogContext.

Transforming a String to a File using View Transformer

I'm currently using a crud application to create a blog style site.
The blog object requires an upload of a file, which I store in the database as a string. However, when I try to edit an existing Blog, I get this error.
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.
I'm trying to figure out how to do this. A google search did point me to the page where view transformers a re explained. But the example there shows how to transform a string to an Entity (and Issue). However, I'm not sure if this is exactly the way I should handle this, since the object I am trying to transform a string into is a class Symfony\Component\HttpFoundation\File\File. I was just wondering of anyone know how I could go about doing this. I'm under the impression that I would have to get a actual file type of the class Symfony\Component\HttpFoundation\File\File and that is what I am stumped on. How does one do this?
Ok. so it did take me a while to figure this out, but it was my first time. Essentially what I did was use the CallBackTranformer() function in the BlogType.php class and transformed the object, in this case the File to a null object when rendering it in the form, and then just returned it in the other direction.
Here is the code, in case anyone wants to see it.
$builder->get('imageUrl')->addModelTransformer(new CallBackTransformer(
function($imageUrl) {
return null;
},
function($imageUrl) {
return $imageUrl;
}
));
In your updateAction or editAction in the begining of method add somethink like this:
public function updateAction(Request $request ,$posts) {
$posts->setFile(
new File($this->getParameter('images_directory').'/'.$posts->getFile()
));
Just like in the symfony site:
https://symfony.com/doc/3.2/controller/upload_file.html
use Symfony\Component\HttpFoundation\File\File;
// ...
$product->setBrochure(
new File($this->getParameter('brochures_directory').'/'.$product->getBrochure())
);

Return view not picking up new view

I am trying to change the view that on of my controllers points to however this is not picking up the amendment. The following is the code I am trying to use;
// GET: UserDemographics/Create
public ActionResult Create()
{
return View("Manage");
}
And my views folders look like below:
My understanding is that View tries to check for the same name as the method but I may be wrong. Any help would be appreciated.
Nothing wrong in your code. This should work perfectly
Your URL should be like this,
localhost:[Port Number]/userdemographics/Create
If you already hosted your project in a real domain, then you can replace localhost:[Port Number] with your domain name. For example,
www.example.com/userdemographics/Create
The view name specified within the View() method does not alter the path in the URL when making a request, it simply changes the name of the view that is rendered as a result of the request.
If you want the path to your action to be /UserDemographics/Manage, you would need to change the name of your Action method to Manage.
public class UserDemographics : Controller
{
// Requested by /UserDemographics/Manage in the browser
public ActionResult Manage()
{
// You don't HAVE to specify the view name here, Manage.cshtml will be rendered based on the convention.
// However as mentioned this is best practice to specify the name.
return View("Manage");
}
}
This makes it so that there is no longer a need to specify the View name as it will be automatically selected from the Views folder by convention for that controller.

Symfony2. Enum: pls explain "You can register this type with Type::addType('enumvisibility', 'MyProject\DBAL\EnumVisibilityType')"

I am trying to implemt the following instruction, as to have Enum type somehow
Shame on me, but I have not an idea on how/where I go to "register [the defined] type with Type::addType('<enummyfield>', 'MyProject\DBAL\<EnumMyfield>Type')".
EDIT Answer 1 helps. It seems I need too:
to move definition of EnumMyfield to directory MyBundle\Doctrine\DBAL\Types\Type (with appropriate use declarations)
to update app\config\config.yml with lines
types:
<myfield>: <mybundle>\Doctrine\DBAL\Types\Type\<EnumMyfield>Type
since I wish to have a Select on the Form side, to define:
->add('MyField','choice', array('label'=>'Select please', 'choices'=>array('A'=>'A','B'=>'B')), within my MyentityType\buildForm().
With respect to the last point, if I just use choices'=>array('A','B'), values for the select options are rendered as numbers (0,1), and I run into an error (I am not sure why)
your comments/advises are welcome
Just a recap, useful for others (maybe); I will highlight were you're blocked
Create a directory Doctrine\DBAL\Types
Define your new DBAL type there like shown into your link
Register it into your bundle main file (*) <--- this is what you're missing
Use it into entity definition
(*) You have a file inside your bundle named YourBundleNameBundle.php this file is used to register the bundle. If you want to register your custom type also, put inside this bundle the string Type::addType('enum', 'MyProject\DBAL\EnumType')".
So, something like
public function boot()
{
if (false === Type:hasType('enum')) {
$em = $this->container->get('doctrine.orm.entity_manager');
Type::addType('enum', 'Path\To\Bundle\Doctrine\DBAL\Types\EnumType');
$em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('enum','enum');
}
}
Don't forget the use statement
use Doctrine\DBAL\Types\Type;
at the top of the file

Property Get Value Based on Condition

I want to create a class that returns a path in a string based on a Boolean. For instance, I have a property called ErrorLog. If the current environment is development, the string returned for the property is "C:\LogFiles\AppLogs\ErrorLogs" and in production, the string returned would be "D:\LogFiles\AppLogs\ErrorLogs"
I can determine the environment in a method and return a boolean - I just don't know how to return the correct path. I have been looking at conditional properties, but am not sure this is the best method.
You should look at Web.config transformations since you are using VS 2010. With this you can set up the path to the log file in the appSettings section and have it automatically changed to the appropriate value when you deploy your app to Production.
There's a very complete example here.
You can use this
protected String ErrorLog
{
get {return YourMethodThatReturnTrueIfDevelopment() ? "C:\LogFiles\AppLogs\ErrorLogs" : "D:\LogFiles\AppLogs\ErrorLogs";}
set {ErrorLog = value;}
}
Define the Get method, returning a Bool that eval which enviroment is, and then use the ternary operator to return one or another string.
Anyway, this is how to do what you ask; I recommend (after seeing) the Icarus' answer

Resources