I'm running into a severe problem, In fact I'm not well understanding recess naming convention for relationship. I personally think it should be more documented with concrete examples. Hopefully, if i get to understand it, I can start to write some examples.Also, if someone has well understand Recess relationship convention well, in case, he can explain it here, it would be great
I have two table, all table names are in the database are the lower case of the model names. All fields names are same to the models' attributes
Post---->Comment(A Post can have several comments)
Model Post:
<?php
/**
* !Database Default
* !Table post
* !HasMany comment, Class:try.models.Comment,Key:postId
*/
class Post extends Model
{
/** !Column PrimaryKey, Integer, AutoIncrement */
public $postId;
/** !Column String */
public $name;
}
?>
Model Comment:
<?php
/**
* !Database Default
* !Table comment
* !BelongsTo post
*/
class Comment extends Model {
/** !Column PrimaryKey, Integer, AutoIncrement */
public $commentId;
/** !Column String */
public $name;
}
?>
However, when I'm doing the following, I'm getting an error
<?php
Library::import('try.models.Post');
Library::import('try.models.Comment');
Library::import('recess.framework.controllers.Controller');
/**
* !RespondsWith Layouts
* !Prefix Views: home/, Routes: /
*/
class TryHomeController extends Controller {
/** !Route GET */
function index()
{
$this->flash = 'Welcome to your new Recess application!';
$Post= new Post(5);
$Comments=$Post->comment();
}
}
?>
However, I'm getting this error
try.models.Comment has not been imported.
Look in your Post model at the Class line
**
* !Database Default
* !Table post
* !HasMany comment, **Class:try.models.Comment**,Key:postId
*/
Here you are including the full classpath, try.models.Comment. You only need to specify Comment as the class to include. Be sure that your file names follow the ClassName.class.php convention.
Related
I have a pre-existing Oracle database that I want to exploit.
To do this, I created 2 classes that I map with many-to-one and one-to-many. But there are elements of which the first class have no correspondence in the second class, however id exists. It does not return any error.
I would like that it sends me rather a null. How to do that ?
class Fact
{
/**
*
* #ORM\OneToMany(targetEntity="present\UserBundle\Entity\March",mappedBy="fact", cascade={"persist","remove"})
*/
private $march;
}
class March
{
...
/*
* #var \present\PublishBundle\Entity\image
* #ORM\ManyToOne(targetEntity="present\UserBundle\Entity\fact",inversedBy="march", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id",referencedColumnName="id")
* })
* })
*/
private $facture;
}
the error
Entity of type 'present\UserBundle\Entity\Client' for IDs id(0) was not found
Thanx you
I haven't tested your code but I think your error has to do your JoinColumn declaration :
#ORM\JoinColumn(name="id",referencedColumnName="id")
In the documentation here it says that the name attribute will define the name of the column for your relation.
But here "id" is also referencing to your primary key I suppose.
To solve it, try to change the name="id" by name="march_id", or remove the JoinColumn.
Edit : I have read a bit to quickly the error, haven't seen it's referencing to Client entity, can you show the code related to this relation too ?
I have a File entity for handle files upload in other entities (news/blog/etc).
I point to it with a OneToOne relation and it works fine. But I would change the upload dir, for each relation entity :
upload/news
upload/blog
The upload path is set in my file entity so i dont know how to automaticaly update the path foreach relations...
do you have an idea on how to do it ?
Thanks
Of course you can do it.
On your file entity side, you can add a uploadDir attribute, and create a setter like this :
private $uploadDir;
public function setUploadDir($uploadDir)
{
if (!$this->uploadDir) {
$this->uploadDir = $uploadDir;
}
}
your comment suggest you use Symfony with Doctrine right ?
So you can edit the classical getUploadDir() method like this:
protected function getUploadDir()
{
return 'uploads/' . $this->uploadDir;
}
In the 'parent' entity you have to update this attribute (when it is created) before persist or update.
(I personally use life cycle callbacks but you can do it manually in your controller)
use Doctrine\ORM\Mapping as ORM;
/**
* News
*
* #ORM\Table(name="News")
* #ORM\HasLifecycleCallbacks
*/
class News
{
//....
/**
* #ORM\OneToOne(targetEntity="File",cascade={"persist","remove"})
*/
private $file;
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
function setUploadDir()
{
$this->getFile()->setUploadDir('news');
}
// ....
You can also add a constant to make the code cleaner...
I hope it'll help you
I'm totally new to the CakePhp framework, so I'm doing the basic tutorial. So far so good, I built the scaffolding for my models, authentication works fine, but I't a little excessive: I would like to allow one action ('index' for example) to be allowed even for non-authenticated users.
I suspect it must have something with "BeforeFilter()", but any solution I tried hasn't worked - probably because they'for CPHP 2.0, and/or I'm dumb
.
The code is here, though it's not particuolarily interesting since it's the one generated by the scaffolding mechanism.
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* Frutta Controller
*
* #property \App\Model\Table\FruttaTable $Frutta
*/
class FruttaController extends AppController
{
/**
* Index method
*
* #return void
*/
public function index()
{
$this->set('frutta', $this->paginate($this->Frutta));
$this->set('_serialize', ['frutta']);
}
//cut..
}
Use the following:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index'); //allow index without authentication
}
Reference : http://book.cakephp.org/3.0/en/controllers/components/authentication.html#making-actions-public
I am still learning Symfony2 and don't understand how to upload a file.
Don't worry, I've already checked the documentation. It's really good, but my problem isn't explained in any tutorial.
I am looking for guidance on how to upload a file with Symfony2 but with all the thing everybody needs (such as constraint of extension, rename of the file based on the id and stuff, store the path in the db, etc...)
I found good tutorials, tried to mixed them but with no success. Each time a different problem appears: file re-uploads on every submit on the form (even if the file field is empty), guessExtension impossible to used, tmp path stored in the database instead of the right path, file not moved, impossible to used the id in the rename because the id is on auto-increment and so not yet generated).
So, I'll put an 'standard' entity, let say: Photo.php
/**
* Photo
*
* #ORM\Table(name="photo")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Photo
{
// Annotation for the id and auto increment etc
private $id;
/**
* #var string
* #Assert\File( maxSize = "3072k", mimeTypesMessage = "Please upload a valid Image")
* #ORM\Column(name="image", type="string", length=245, nullable=false)
*/
private $image
private $title
private $description
// all the function get, set for the 4 previous variables
}
and the controller:
public function addPhotoAction()
{
$add_photo = new Photo;
$formBuilderPhoto = $this->createFormBuilder($add_photo);
$formBuilderPhoto
->add('title','text',array('label' => 'Title of the photo', 'required' => true))
->add('image','file', array('required' => true, 'data_class' => null))
->add('description','textarea',array('label' => 'Description of your photo', 'required' => false))
;
$form_photo = $formBuilderPhoto->getForm();
if ($request->getMethod() == 'POST') {
$form_photo->bind($request);
if ($form_photo->isValid()) {
// ...
}
}
return $this->render('MyBundle:frontend:photo.html.twig',
array('form_photo' => $form_photo->createView())
);
}
Do you know now what are the 'important' function to add to be able to upload the photo and rename it ?
How do you check the extension to see if the upload is possible?
What is your actual way of doing such a thing with Symfony2? I know there is a lot of Bundle that do all those things for you but I want to learn to do it and understand the process.
What is the 'classic' way to implement a file upload form and rename function with Symfony2?
Do you know now what are the 'important' function to add to be able to upload the photo and rename it?
See the official documentation on how to do this. There are good working examples for a simple file upload. Also check the doctrine documentation for lifecycle callbacks.
How do you check the extension to see if the upload is possible?
There is some HTML-Form validation in each browser. See this question for the HTML accept="" attribute in input elements. Also in Symfony2 you can specify the MIME-type of an uploaded file using this annotation:
/**
* #Assert\File(
* maxSize = "1024k",
* mimeTypes = {"application/pdf", "application/x-pdf"},
* mimeTypesMessage = "Please upload a valid PDF"
* )
*/
Even though you did not want to use any bundles I'll have to recommend you the KnpDoctrineBehavioursBundle which makes file uploading way easier.
Step-by-step:
Because you read the documentation already I'll give you a step by step code-example.
First of all you need an entity. Let's call it Image:
/**
* Class Image
*
* #ORM\Entity()
* #ORM\HasLifecycleCallbacks
*/
class Image extends BaseEntity
{
Note the #ORM\HasLifecycleCallbacks annotation. It is very important and you need it later. We create all the basic fields like ID and what not. Also we need a field to store the file path in:
/**
* Image path
*
* #var string
*
* #ORM\Column(type="text", length=255, nullable=false)
*/
protected $path;
And one for the Image itself. Here we also define the Validation for the images. In my example it has to be 5M big and of one of the defined mimeTypes. It should be self-explanatory. Otherwise the official docs help as always.
/**
* Image file
*
* #var File
*
* #Assert\File(
* maxSize = "5M",
* mimeTypes = {"image/jpeg", "image/gif", "image/png", "image/tiff"},
* maxSizeMessage = "The maxmimum allowed file size is 5MB.",
* mimeTypesMessage = "Only the filetypes image are allowed."
* )
*/
protected $file;
Add all the Getters & Setters and update your database schema with this command:
php app/console doctrine:schema:update --force
Next we need the lifecycles. They are methods in the Entity that are called on certain events. For example the #ORM\PreUpdate() annotation before a method says that this method is being called right before the entity gets updated.
/**
* Called before saving the entity
*
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$filename = sha1(uniqid(mt_rand(), true));
$this->path = $filename.'.'.$this->file->guessExtension();
}
}
Before the entity gets stored or updated this method is called. You can use it to e.g. generate a unique file name.
/**
* Called before entity removal
*
* #ORM\PreRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
Called before the entity gets removed. This gives you time to delete the image from your folders or log a message if you want to.
/**
* Called after entity persistence
*
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
// The file property can be empty if the field is not required
if (null === $this->file) {
return;
}
// Use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and then the
// target filename to move to
$this->file->move(
$this->getUploadRootDir(),
$this->path
);
// Set the path property to the filename where you've saved the file
//$this->path = $this->file->getClientOriginalName();
// Clean up the file property as you won't need it anymore
$this->file = null;
}
This is the important part where your file is actually moved to the right directory. Note that I have used some additional methods. You can all get them from the official docs.
Next thing you need is a form. The form class itself is very simple. Just make sure you set the default data_class like this:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'FSchubert\SiyabongaBundle\Entity\Image',
)
);
}
A file upload field can be created very easily in the buildForm() method:
$builder->add('file', 'file');
The methods for your Controller are a little long for just pasting them here and IMHO it's not part of answering your question. There are countless examples out there for writing a proper Controller Action for your purpose.
More things you have to keep in mind:
You need to give your app writing permissions to the folders you upload the files to. Although it seems obvious it can be annoying if you have multiple servers you run the application on.
There is an Image Constraint for your entity as well. You can find it here. But since you were talking about a file upload I used the File Constraint instead.
As I mentioned in the top of this post, there are many Bundles that handle all these things for you. Check them out if you want an easy life.
Edit:
Changed from DoctrineExtensionsBundle to DoctrineBehaviours since development on the old one stopped in favour of the DoctrineBehaviours bundle.
I recommend you to use vlabs media bundle.
The VichUploaderBundle is also easy to use for uploading files:
https://github.com/dustin10/VichUploaderBundle
I recommend VichUploader bundle and this code with the bundle implanted in the entity and the FormType.
composer require vich/uploader-bundle
Admission.php
/**
* #ORM\Entity(repositoryClass=AdmissionRepository::class)
* #Vich\Uploadable
*/
class Admission
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $cin;
/**
* #Vich\UploadableField(mapping="product_image", fileNameProperty="cin")
* #var File
*/
private $cinFile;
public function getId(): ?int
{
return $this->id;
}
public function getCin(): ?string
{
return $this->cin;
}
public function setCin(string $cin): self
{
$this->cin = $cin;
return $this;
}
}
AdmissionType.php
class AdmissionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('cinFile', VichFileType::class);
}
vich_uploader.yaml
vich_uploader:
db_driver: orm
mappings:
product_image:
uri_prefix: /uploads
upload_destination: '%kernel.project_dir%/public/uploads'
inject_on_load: false
delete_on_update: true
delete_on_remove: true
namer: vich_uploader.namer_origname
I'm using this plugin with CakePHP --> TwitterBootstrap, everything works like a glow except I can't change the layouts. ie. index, add and such.
I have a model called Cinema and have created this with cake bake and the same thing with Views/Cinemas
This is my controller:
<?php
App::uses('AppController', 'Controller');
/**
* Cinemas Controller
*
*/
class CinemasController extends AppController {
/**
* Layout
*
* #var string
*/
public $layout = 'bootstrap';
/**
* Scaffold
*
* #var mixed
*/
public $scaffold;
}
Have i overridden CakePHPs routes into some special scaffolding template?
By defining public $scaffold; in your controller, you tell Cake that you want to enable Scaffolding mode, which allows you to easily insert/edit/delete some records. The scaffolding mode always uses your "default" layout.
In other words, by defining the public $scaffold; variable, you "overrule" your layout. Scaffolding mode doesn't adopt that setting. Simply remove the public $scaffold; line to get back to your bootstrap layout.