Transforming a String to a File using View Transformer - symfony

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())
);

Related

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

Confused by Symfony's file upload documentation

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'));
}

How to reference $this-> in a different php file

To be specific, I don't really know what I am doing, but I'm trying to reference $this from another file.
I'm working with Wordpress(subscribe2 plugin) and trying to get the function of subscribing to specific categories from the plugin and putting it into my own signup form.
The ability to do this is already in the settings for the plugin, so I'd like to put them in my own form, but they look like this:
$this->get_usermeta_keyname('s2_subscribed')
so my question: How do I reference "$this" in my own file? I have been googling it all morning, but all of my results see "$this" as "this" and don't show me what I want.
$this refers to the current class context. So if you have a class named MyClass, within that class you can access functions and elements using $this. Outside of that class, $this has no context and won't work, but if you have instantiated the class and if the functions or variables are public, then you can access them via a reference to the class.
Example:
<?php
Class MyClass {
$class_var = "Class Var Value";
function class_func_1() {
print $this->class_var;
$this->class_func_2();
}
function class_func_2() {
print "Class Func 2";
}
}
?>
So the dummy class above uses $this to reference its own elements. But outside the class you cannot reference them with this. But if we instantiate an instance of the class, we can access them by the reference to the instance of the class:
<?php
print $this->class_var; // Fails miserably
$this->class_func_1(); // Also fails
$class_instance = new MyClass();
print $class_instance->class_var; // Var access works
$class_instance->class_func_1(); // Call method works
?>
Since this is a wordpress function, I'm curious if you are trying to access something in a plugin (which might use a class) or possibly something in a purchased theme. Either way, there should be a reference to the instance of the class somewhere in the file. Once you have this variable, then you can access the actions and contents of the class.
With more information, I think we can probably provide better direction...
Update:
Ok, it appears you are using the subscribe2 plugin. At the bottom of the plugin file (subscribe2.php) is this line:
$mysubscribe2 = new subscribe2();
What this is doing is creating a global variable that points to an instance of the class. So instead of using $this->method_name() you could use $mysubscribe2->method_name().
However, looking at the file you posted - it almost looks like you grabbed a portion of the plugin code and just put it into a template. I'm not sure what you are trying to accomplish but from here it appears you are heading down a rough path...

Dynamically chose type depending on JSON content

In an ASP.NET MVC 4 application I get a JSON response from an external server that contains an array of "fields". Each field is of an individual type and contains an array of values of that type.
I'd like to deserialize that JSON either into a DynamicObject so that I can access the indivudual value propreties or I need some kind of a child class chooser which decides which class, derived from a "ValueBase" class, is needed to access the different properties of the individual value object.
I hope you know what I mean... it's a little bit complicating.
I've already tried to deserialize it into a DynamicObject (a class that derives from DynamicObject that is). But I get error messages when accessing that object's dynamic properties in the View that the properties I'd like to display don't exist.
So how does a class that derives from DynamicObject have to look like to accept and grant access to the individual differen "value"-properties provided by the JSON code?
And if that wasn't possible or the wrong way to go, how would I have to implement a suitable type chooser class?
Thanks a lot!
I've kinda solved it myself.
Instead of directly converting the returned JSON object (a JSON array to be more precise) into a specific class I fetch it as a dynamic and give it into the constructor of a class that contains a collection of instances of another class the object actually ought to be of (I get a JSON array returned from the webservice anyway). In the constructor of the collection class I decide depending on a value of the JSON object of which inherited class the new object is gonna be and put that into the collection. Yeah, I walked that way afoot somehow but it works.
Looks like this:
public CollectionClass(dynamic dyn)
{
foreach(var item in dyn.items) {
switch((string)item.external_id) { // might have used a Dictionary instead but...
case "member":
this._collection.Add(new Member(item));
break;
case "date":
this._collection.Add(new Date(item));
break;
default: break;
}
}
}
The Member-class itself contains a similar constructor which also requires a dynamic parameter. And it also "builds itself up" depending on values inside the item.
If there's any easier way or a "royal road" of achieving this I'd be grateful for any further advice.

How do I get an ID after saving an ExtBase Model?

After creating a model and adding it to a repository I want to have the new ID for different purposes (creating a mail, updating other fields outside the Extbase world)
$page = t3lib_div::makeInstance('Tx_MyExt_Domain_Model_Page');
$page->setTitle('Hello World');
$this->pageRepository->add($page);
At this point $page hasn't got an ID yet, uid is null.
$page->getUid(); // returns null
When does it get it? And how can I retrieve in on runtime?
In ExtBase, objects are "managed". This means every persistence transaction (add/remove/update) is simply noted in the underlying logic, but not yet executed until the appropriate time (like the end of processing a request). So, just because you add an object to a repository doesn't mean that it's actually added yet. That actually happens once $persistenceManager->persistAll() is called, which isn't something you need to do manually, ever. The point is, your $page object won't have a UID until it's saved and that's why $page->getUid() returns null. Look here for a great explanation.
I suspect that you are trying to do something outside of the ExtBase object/MVC lifecycle. At least, last time I got null when I tried to get the UID of an object, it was because I wasn't operating within the framework appropriately.
However, if you post some more code and give us a bigger picture of what you're trying to achieve, maybe we can help you get to a point where that object actually has a UID. For instance, if you're in a Controller object, tell us which Action method you're in, or if you're in a Repository object, tell us what you're trying to get from the repository and where/how you plan on using the query results.
EDIT
Just guessing here, but I'm assuming you're executing this code in some action of a controller. Since after the controller is executed a view is rendered, you can just pass the page object to the view:
$this->view->assign('page', $page);
And then in your view you can use the page object in a link:
<f:link.action action="show" arguments="{page:page}">
See this page object
</f:link.action>
And then in the show action of your controller you can show the page:
public function showAction(Tx_MyExt_Domain_Model_Page $page) {
// Do whatever you need to show the page in the `Show.html` template
}
I really am just guessing here. If you can give us a larger picture of what you're trying to do, what your action methods are supposed to do and things like that, we can answer your question a little more confidently.
(I'm also assuming that your page object isn't a replacement for the regular TYPO3 pages and that they are something totally different. It's much easier to deal with those TYPO3 pages through the backend interface than at the php level.)
You can call persistence manager explicitly in Your controller like this
#TYPO3 4.x
$persistenceManager = $this->objectManager->create('Tx_Extbase_Persistence_Manager');
$persistenceManager->persistAll();
#TYPO3 6.x
$persistenceManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager');
$persistenceManager->persistAll();

Resources