I am using the Silverstripe Swipestripe module for an online store. Because of the number of products the client has, it's not practical to nave them navigate to each individual product through the site tree when they want to make changes to a product (which happens fairly regularly) so I'd like to have a modeladmin to list all products and allow them to search for a product by name/stockcode.
I thought this would be solvable in the same way as DataObjects (and searches seem to suggest that people have done achieved this), however when I navigate to products in ModelAdmin view, I get:
Fatal Error : Call to a member function stat() on a non-object in
/path/to/folder/wwwroot/framework/model/DataObject.php on line 3192
<?php
class ProductAdmin extends ModelAdmin
{
private static $managed_models = array('Product');
private static $url_segment = 'product';
private $menu_title = 'Products';
}
Interestingly, pages and other extensions of the page class do work.
Here is the code for the Product class:
class Product extends Page {
/**
* Flag for denoting if this is the first time this Product is being written.
*
* #var Boolean
*/
protected $firstWrite = false;
/**
* DB fields for Product.
*
* #var Array
*/
private static $db = array(
'Price' => 'Decimal(19,4)',
'Currency' => 'Varchar(3)',
'StockCode' => 'Varchar(255)',
'Stock' => 'Int',
'Featured' => 'Boolean',
'YouTubeID' => 'Varchar(255)'
);
/**
* Actual price in base currency, can decorate to apply discounts etc.
*
* #return Price
*/
public function Amount() {
// TODO: Multi currency
$shopConfig = ShopConfig::current_shop_config();
$amount = new Price();
$amount->setAmount($this->Price);
$amount->setCurrency($shopConfig->BaseCurrency);
$amount->setSymbol($shopConfig->BaseCurrencySymbol);
//Transform amount for applying discounts etc.
$this->extend('updateAmount', $amount);
return $amount;
}
/**
* Display price, can decorate for multiple currency etc.
*
* #return Price
*/
public function Price() {
$amount = $this->Amount();
//Transform price here for display in different currencies etc.
$this->extend('updatePrice', $amount);
return $amount;
}
/**
* Has many relations for Product.
*
* #var Array
*/
private static $has_many = array(
'Attributes' => 'Attribute',
'Options' => 'Option',
'Variations' => 'Variation'
);
/**
* Defaults for Product
*
* #var Array
*/
private static $defaults = array(
'ParentID' => -1,
'Stock' => 999
);
/**
* Summary fields for displaying Products in the CMS
*
* #var Array
*/
private static $summary_fields = array(
'Amount.Nice' => 'Price',
'Title' => 'Title'
);
private static $searchable_fields = array(
'Title' => array(
'field' => 'TextField',
'filter' => 'PartialMatchFilter',
'title' => 'Name'
)
);
/**
* Set firstWrite flag if this is the first time this Product is written.
*
* #see SiteTree::onBeforeWrite()
* #see Product::onAfterWrite()
*/
public function onBeforeWrite() {
parent::onBeforeWrite();
if (!$this->ID) $this->firstWrite = true;
//Save in base currency
$shopConfig = ShopConfig::current_shop_config();
$this->Currency = $shopConfig->BaseCurrency;
}
/**
* Unpublish products if they get deleted, such as in product admin area
*
* #see SiteTree::onAfterDelete()
*/
public function onAfterDelete() {
parent::onAfterDelete();
if ($this->isPublished()) {
$this->doUnpublish();
}
}
/**
* Set some CMS fields for managing Products
*
* #see Page::getCMSFields()
* #return FieldList
*/
public function getCMSFields() {
$shopConfig = ShopConfig::current_shop_config();
$fields = parent::getCMSFields();
//Product fields
$fields->addFieldToTab('Root.Main', new PriceField('Price'), 'Content');
$fields->addFieldToTab('Root.Main', new TextField('StockCode'), 'Price');
$fields->addFieldToTab('Root.Main', new TextField('Stock'), 'Price');
$fields->addFieldToTab('Root.Main', new CheckBoxField('Featured'), 'Content');
$fields->addFieldToTab('Root.Images', new TextField('YouTubeID', 'YouTube Video ID (Taken from the end of the video url. ie https://www.youtube.com/watch?v=ABC123 would be ABC123)'));
//Replace URL Segment field
if ($this->ParentID == -1) {
$urlsegment = new SiteTreeURLSegmentField("URLSegment", 'URLSegment');
$baseLink = Controller::join_links(Director::absoluteBaseURL(), 'product/');
$url = (strlen($baseLink) > 36) ? "..." .substr($baseLink, -32) : $baseLink;
$urlsegment->setURLPrefix($url);
$fields->replaceField('URLSegment', $urlsegment);
}
if ($this->isInDB()) {
//Product attributes
$listField = new GridField(
'Attributes',
'Attributes',
$this->Attributes(),
GridFieldConfig_BasicSortable::create()
);
$fields->addFieldToTab('Root.Attributes', $listField);
//Product variations
$attributes = $this->Attributes();
if ($attributes && $attributes->exists()) {
//Remove the stock level field if there are variations, each variation has a stock field
$fields->removeByName('Stock');
$variationFieldList = array();
foreach ($attributes as $attribute) {
$variationFieldList['AttributeValue_'.$attribute->ID] = $attribute->Title;
}
$variationFieldList = array_merge($variationFieldList, singleton('Variation')->summaryFields());
$config = GridFieldConfig_HasManyRelationEditor::create();
$dataColumns = $config->getComponentByType('GridFieldDataColumns');
$dataColumns->setDisplayFields($variationFieldList);
$listField = new GridField(
'Variations',
'Variations',
$this->Variations(),
$config
);
$fields->addFieldToTab('Root.Variations', $listField);
}
}
//Ability to edit fields added to CMS here
$this->extend('updateProductCMSFields', $fields);
if ($warning = ShopConfig::base_currency_warning()) {
$fields->addFieldToTab('Root.Main', new LiteralField('BaseCurrencyWarning',
'<p class="message warning">'.$warning.'</p>'
), 'Title');
}
return $fields;
}
/**
* Get the URL for this Product, products that are not part of the SiteTree are
* displayed by the {#link Product_Controller}.
*
* #see SiteTree::Link()
* #see Product_Controller::show()
* #return String
*/
public function Link($action = null) {
if ($this->ParentID > -1) {
return parent::Link($action);
}
return Controller::join_links(Director::baseURL() . 'product/', $this->RelativeLink($action));
}
/**
* A product is required to be added to a cart with a variation if it has attributes.
* A product with attributes needs to have some enabled {#link Variation}s
*
* #return Boolean
*/
public function requiresVariation() {
$attributes = $this->Attributes();
return $attributes && $attributes->exists();
}
/**
* Get options for an Attribute of this Product.
*
* #param Int $attributeID
* #return ArrayList
*/
public function getOptionsForAttribute($attributeID) {
$options = new ArrayList();
$variations = $this->Variations();
if ($variations && $variations->exists()) foreach ($variations as $variation) {
if ($variation->isEnabled()) {
$option = $variation->getOptionForAttribute($attributeID);
if ($option) $options->push($option);
}
}
$options = $options->sort('SortOrder');
return $options;
}
/**
* Validate the Product before it is saved in {#link ShopAdmin}.
*
* #see DataObject::validate()
* #return ValidationResult
*/
public function validate() {
$result = new ValidationResult();
//If this is being published, check that enabled variations exist if they are required
$request = Controller::curr()->getRequest();
$publishing = ($request && $request->getVar('action_publish')) ? true : false;
if ($publishing && $this->requiresVariation()) {
$variations = $this->Variations();
if (!in_array('Enabled', $variations->map('ID', 'Status')->toArray())) {
$result->error(
'Cannot publish product when no variations are enabled. Please enable some product variations and try again.',
'VariationsDisabledError'
);
}
}
return $result;
}
}
Can anyone suggest what I'm doing wrong here or an alternative way to do what I'm trying to achieve?
Cheers
Just in case anyone still having the same problem.
So, it happens if you have installed Product Categories module for swipestripe.
The cause of this is private static $searchable_fields in ProductCategory_Extension class in ProductCategory.php file in that module. Just comment out that field and it will work.
It is because the dataobject class tries to stat Category as a class - which obviously doesnt exist.
I will fix it and push to github if I get some time. Just wanted to update here so that others dont waste time scratching head why it doesnt work.
Related
I'm trying to clean up some code done in a messy way and right now I'm having trouble with doctrine's paginator.
When I'm accessing a page that handle paginator in order to show all different articles of my blog I'm getting this error:
Neither the property "id" nor one of the methods "id()", "getid()"/"isid()"/"hasid()" or "__call()" exist and have public access in class "Doctrine\ORM\Tools\Pagination\Paginator".
In doctrine vendor bundle those methods are not set but my entity have them and I know that it is forbidden to edit a vendor file. I'm missing something because I don't know if I should extend my paginator entity and add those missing methods or is there a little bit more to do ?
I just started symfony and I know that my bases are not enough to understand it all by myself.
Thank you very much for you time and attention.
Here is my Article controller for route category:
/**
* #Route("/categorie/{id}", name="categorie")
*
* #param Request $request
* #param Helper $helper
* #param AuthorizationCheckerInterface $authChecker
* #param DocumentCategory $categorie
* #param TwitterService $twitterService
*
* #return RedirectResponse|Response
*/
public function categorie(
Request $request,
Helper $helper,
AuthorizationCheckerInterface $authChecker,
DocumentCategory $categorie,
TwitterService $twitterService
) {
if (!$authChecker->isGranted('IS_AUTHENTICATED_FULLY')
&& !$authChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return $this->redirectToRoute('login');
}
$page = (int) ($request->get('page'));
if (0 === $page) {
$page = 1;
}
$userType = $this->getDoctrine()->getRepository('App:User')
->getManagerExpertCollabo($this->getUser());
$articleAlaUneListe = [];
$articleIdListe = $helper->getArticleIdAuth($authChecker);
$articleListe = $this->getDoctrine()
->getRepository('App:Document')
->getPage(
self::ITEM_PER_PAGE * ($page - 1),
self::ITEM_PER_PAGE,
'document.dateCreated',
'DESC',
'(documentCategory.id = \''.$categorie->getId().'\' and '.$helper->baseRequestArticle().')',
7,
[],
$articleIdListe
);
[$articlePopulaireListe, $categorieListe, $totalPage] = $this->getPopularArticleList(
$articleListe,
$helper,
$articleIdListe
);
$articlesList->getDocuments();
$feedData = $twitterService->getTwitterFeed();
return $this->render('article/list.html.twig', [
'pageClass' => 'backoffice withFooterLarge dashboard',
'totalPage' => $totalPage,
'page' => $page,
'feedData' => $feedData,
'categorieListe' => $categorieListe,
'categorie' => $categorie,
'articleAlaUneListe' => $articleAlaUneListe,
'articlePopulaireListe' => $articlePopulaireListe,
'articleListe' => $articleListe, ]);
}
Here is the document entity for categories field:
/**
* #ORM\JoinTable(name="ht_lk_document_category"),
* #ORM\ManyToMany(targetEntity="App\Entity\DocumentCategory", inversedBy="documents")
*/
private $categories;
/**
* #return Collection|array<DocumentCategory>
*/
public function getCategories(): Collection
{
return $this->categories;
}
public function setCategories($category): self
{
$this->categories = $category;
return $this;
}
Here is the DocumentCategory entity :
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Document", mappedBy="categories")
*/
private $documents;
/**
* #return Collection|Document[]
*/
public function getDocuments(): Collection
{
return $this->documents;
}
Here is the Document Repository :
public function getPage($first_result, $max_results, $orderby, $direction, $criteria, $documentType = null, $searchWordArray = [], $articleIdListe = '')
{
$qb = $this->createQueryBuilder('docArticle');
$qb->select('docArticle')
->addSelect('documentCategory', 'documentCategory')
->addSelect('user', 'user')
/*
if(sizeof($searchWordArray) > 0){
$fieldIndice = 1;
foreach($searchWordArray as $searchWord){
$qb->andWhere('(document.name_fr LIKE ?'.$fieldIndice.' or document.name_en LIKE ?'.$fieldIndice.' or document.content_fr LIKE ?'.$fieldIndice.' or document.content_en LIKE ?'.$fieldIndice.')');
$qb->setParameter($fieldIndice++, '%'.$searchWord.'%');
}
} */
->leftJoin('docArticle.categories', 'documentCategory')
->leftJoin('docArticle.author', 'user')
->setFirstResult($first_result)
->setMaxResults($max_results);
if (!empty($criteria)) {
$qb->where('('.$criteria.')');
}
if (!empty($orderby)) {
$qb->orderBy($orderby, $direction);
}
$pag = new Paginator($qb->getQuery());
$qb->setFirstResult(0);
$qb->setMaxResults(PHP_INT_MAX);
$sql = $qb->getQuery()->getSql();
if ('()' !== $articleIdListe) {
$qb->where('(docArticle.id IN '.$articleIdListe);
}
$compte = \count($qb->getQuery()->getScalarResult());
return ['page' => $pag, 'compte' => $compte];
}
And finally here is the Document Category Repository :
/**
* #param $first_result
* #param $max_results
* #param $orderby
* #param $direction
* #param $criteria
* #param int|null $documentType
* #param array $searchWordArray
* #param string $articleIdListe
*
* #return array
*/
public function getPage(
$first_result,
$max_results,
$orderby,
$direction,
$criteria,
$documentType = null,
$searchWordArray = [],
$articleIdListe = ''
) {
$qb = $this->createQueryBuilder('document');
$qb->select('document')
->addSelect('documentCategory', 'documentCategory')
->addSelect('user', 'user')
->addSelect('documentType', 'documentType');
if (\count($searchWordArray) > 0) {
$fieldIndice = 1;
foreach ($searchWordArray as $searchWord) {
$qb->andWhere(
'('
.'document.name_fr LIKE ?'.$fieldIndice
.' or document.name_en LIKE ?'.$fieldIndice
.' or document.content_fr LIKE ?'.$fieldIndice
.' or document.content_en LIKE ?'.$fieldIndice
.')'
);
$qb->setParameter($fieldIndice++, '%'.$searchWord.'%');
}
}
if ($documentType) {
if (\mb_strlen($articleIdListe) > 3) {
$qb->andWhere('(documentType.id = :documentType OR document.id IN '.$articleIdListe.')')
->setParameter('documentType', $documentType);
} else {
$qb->andWhere('(documentType.id = :documentType)')
->setParameter('documentType', $documentType);
}
}
$qb->leftJoin('document.categories', 'documentCategory')
->leftJoin('document.documentType', 'documentType')
->leftJoin('document.author', 'user')
->setFirstResult($first_result)
->setMaxResults($max_results)
->andWhere('document.documentType<>6');
if (!empty($criteria)) {
$qb->andWhere('('.$criteria.')');
}
if (!empty($orderby)) {
$qb->orderBy($orderby, $direction);
}
$sql = $qb->getQuery()->getSql();
$pag = new Paginator($qb->getQuery());
dump($pag);
$qb->setFirstResult(0);
$qb->setMaxResults(PHP_INT_MAX);
$sql = $qb->getQuery()->getSql();
$compte = \count($qb->getQuery()->getScalarResult());
return ['page' => $pag, 'compte' => $compte];
}
/**
* #param int|null $documentType
*
* #return array
*/
public function getArticleIdList($documentType = null)
{
$qb = $this->createQueryBuilder('document');
$qb->select('document.id');
if ($documentType) {
$qb->where('(document.documentType = :documentType)')
->setParameter('documentType', $documentType);
}
$compte = $qb->getQuery()->getScalarResult();
return $compte;
}
(I deleted all unnecessary method for this question)
Add the following code to the entity class from which you want to show data:
public function getId(): ?string
{
return $this->id;
}
Or
if you do not want the property "id" to be displayed in the view, comment out or delete the lines of code in your Twig template for the entity in question. For example, delete
<td>{{ Category.id }}</td>
I tried to get all products with suitable skus in Magento 2.
What i did:
$currentSku = $_product->getSku();
$currentSku = substr($currentSku, 0, 3);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
/** #var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */
$productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\Collection');
$productCollection->addFieldToFilter('sku', array('like' => ''.$currentSku.' %'));
/** Apply filters here */
$productCollection->load();
The collection is always empty but there are suitable products.
I tried to filter the collection by name and this worked.
There is a space after your SKU.
Change it to
$productCollection->addFieldToFilter('sku', array('like' => ''.$currentSku.'%'));
Try this,
public function __construct(
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
....
) {
$this->_productCollectionFactory = $productCollectionFactory;
...
}
public function getProducts($currentSku)
{
/** #var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
$collection = $this->_productCollectionFactory->create()
->addAttributeToSelect('*')
->addAttributeToFilter('status', array('eq' => 1))
->addAttributeToFilter('sku', array('like' => $currentSku.'%'))
->addStoreFilter()
->load();
return $collection;
}
I am trying to create a checkout that allows a user to create an account for a fee (premium accounts, if you will). A user will create an account (marked as unpaid), the user will pay, and then on a successful payment the account is marked as paid. I can create an account, and I can make a charge. My problem is linking the two things together. I'm not sure how to reference the created account from the successful charge. Here is what I have so far.
Payment.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\ArrayObject;
/**
* #ORM\Table
* #ORM\Entity
*/
class Payment extends ArrayObject
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*
* #var integer $id
*/
protected $id;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
CreateProfileController.php
CreateAction
public function createASquareAction(Request $request, $coupon)
{
$newUser = new User();
$registrationForm = $this->getRegistrationForm($newUser);
$registrationForm->handleRequest($request);
if ($registrationForm->isSubmitted() && $registrationForm->isValid()) {
$newSquare = new Square();
$newSquare->setProduct($registrationForm->get('product')->getData());
$newUser->addSquare($newSquare);
$cost = $this->getTotal($newSquare->getProduct(), $registrationForm->get('coupon')->getData());
$noPayment = $this->isAdmin() || $cost == 0;
$em = $this->getDoctrine()->getManager();
$em->persist($newUser);
$em->flush();
if ($noPayment) {
$newSquare->setVerified(true);
$em->persist($newSquare);
$em->flush();
return $this->redirectToRoute('edit', array(
'id' => $newSquare->getMsid()
));
} else {
$gatewayName = 'stripe_checkout_test';
$storage = $this->get('payum')->getStorage('AppBundle\Entity\Payment');
$payment = $storage->create();
$payment["amount"] = $cost;
$payment["currency"] = 'USD';
$payment["description"] = "Memorysquare";
$storage->update($payment);
$captureToken = $this->get('payum')->getTokenFactory()->createCaptureToken(
$gatewayName,
$payment,
'test_payment_done' // the route to redirect after capture;
);
return $this->redirect($captureToken->getTargetUrl());
}
}
return $this->render('create-a-square/create-a-square.html.twig', [
'registrationForm' => $registrationForm->createView(),
'coupon' => $coupon,
]);
}
Payment Complete Action
public function testPaymentDoneAction(Request $request)
{
$token = $this->get('payum')->getHttpRequestVerifier()->verify($request);
$identity = $token->getDetails();
$model = $this->get('payum')->getStorage($identity->getClass())->find($identity);
$gateway = $this->get('payum')->getGateway($token->getGatewayName());
// or Payum can fetch the model for you while executing a request (Preferred).
$gateway->execute($status = new GetHumanStatus($token));
$details = $status->getFirstModel();
return new JsonResponse(array(
'status' => $status->getValue(),
'details' => iterator_to_array($details),
));
}
Any help to get me on track would be greatly appreciated.
The answer to this was adding my order entity (or any entity you'd like) to the Payment (or PaymentDetails) entity like so (NOTE the cascade persist):
Payment.php
// ... all previous code ... //
/**
* #ORM\OneToOne(targetEntity="Order", cascade={"persist"})
* #ORM\JoinColumn(name="orderid", referencedColumnName="orderid")
*/
private $order;
/**
* Set order
*
* #param \AppBundle\Entity\Order $order
*
* #return Payment
*/
public function setOrder(\AppBundle\Entity\Order $order = null)
{
$this->order = $order;
return $this;
}
/**
* Get order
*
* #return \AppBundle\Entity\Order
*/
public function getOrder()
{
return $this->order;
}
Then in the payment preparation, I add the new order to the $payment object
public function createASquareAction(Request $request, $coupon)
{
// ... previous code ... //
$newOrder = new Order();
// do some setting on my order
$payment->setOrder($newOrder);
$storage->update($payment);
// ... rest of code ... //
}
Maybe this will help someone in the future. I also created an event subscriber to check the order onUpdate, and mark as paid if the stripe payment was successful.
Is it possible to retrieve the html code generated from controller A within controller B?
Controller A
/**
*
*
* #Route("/{user_id}/cart", name="user_cart")
* #Template()
*/
public function showCartAction($user_id)
{
$cart = $this->getCartManager()
->getUserCart($user_id);
return array(
'cart'=> cart
);
}
Controller B
/**
*
*
* #Route("/html", name="htmlGenerated")
* #Template()
*/
public function showHTMLAction()
{
$user_id = 3;
$html = //How to obtain the html generated by Controller A with UserId = 3 ????
//...
}
You could forward the request in Controller B
public function showHTMLAction()
{
$user_id = 3;
$html = $this->forward('AcmeDemoBundle:ControllerB:showCardAction', array(
'user_id' => $user_id,
))->getContent();
}
Even though this should work perfectly fine, I would actually advise you to embed the controller in your template instead.
I have a form for submitting an article. The form has a category multi-select box that pulls categories from the DB using my Category.php entity. The form generates fine, but I get the following error when trying to submit:
Property "categories" is not public in class "Natknow\EditorBundle\Entity\Article". Maybe you should create the method "setCategories()"?
Template Form Code:
[...]
<div id="artFormG1">
<?php echo $view['form']->row($form['title']) ?>
<?php echo $view['form']->row($form['description']) ?>
<?php echo $view['form']->row($form['source']) ?>
</div>
<div id="artFormG2">
<?php echo $view['form']->row($form['categories']) ?>
</div>
<?php echo $view['form']->row($form['body']) ?>
<br />
<input class="button" type="submit" formnovalidate = "true" />
<?php echo $view['form']->rest($form) ?>
[...]
ArticleType.php - Form Class
[...]
$builder->add('title', 'text', array(
'attr' => array('class' => 'artFormLeft')
));
$builder->add('description', 'text', array(
'attr' => array('class' => 'artFormLeft')
));
$builder->add('source', 'text', array(
'attr' => array('class' => 'artFormLeft')
));
$builder->add('categories', 'entity',
array('class' => 'NatknowEditorBundle:Category',
'property' => 'name',
'expanded' => false,
'multiple' => true,
)
);
$builder->add('body', 'textarea', array(
'attr' => array('class' => 'tinymce'),
));
[...]
Article.php - article Table Entity
[...]
/**
* Add categories
*
* #param Natknow\EditorBundle\Entity\ArticleCategory $categories
*/
public function addArticleCategory(\Natknow\EditorBundle\Entity\ArticleCategory $categories)
{
$this->categories[] = $categories;
}
/**
* Get categories
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCategories()
{
return $this->categories;
}
[...]
ArticleCatigory.php - article_category Table Entity
[...]
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Article", inversedBy="categories", cascade={"all"})
*/
protected $article;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="articles", cascade={"all"})
*/
protected $category;
/**
* #ORM\Column(type="smallint")
*/
protected $isParent = 0;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set isParent
*
* #param smallint $isParent
*/
public function setIsParent($isParent)
{
$this->isParent = $isParent;
}
/**
* Get isParent
*
* #return smallint
*/
public function getIsParent()
{
return $this->isParent;
}
/**
* Set article
*
* #param Natknow\EditorBundle\Entity\Article $article
*/
public function setArticle(\Natknow\EditorBundle\Entity\Article $article)
{
$this->article = $article;
}
/**
* Get article
*
* #return Natknow\EditorBundle\Entity\Article
*/
public function getArticle()
{
return $this->article;
}
/**
* Set category
*
* #param Natknow\EditorBundle\Entity\Category $category
*/
public function setCategory(\Natknow\EditorBundle\Entity\Category $category)
{
$this->category = $category;
}
/**
* Get category
*
* #return Natknow\EditorBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
[...]
Category.php - category Table Entity
[...]
/**
* Add articles
*
* #param Natknow\EditorBundle\Entity\ArticleCategory $articles
*/
public function addArticleCategory(\Natknow\EditorBundle\Entity\ArticleCategory $articles)
{
$this->articles[] = $articles;
}
/**
* Get articles
*
* #return Doctrine\Common\Collections\Collection
*/
public function getArticles()
{
return $this->articles;
}
[...]
The Controller:
[...]
$art = new Article();
$em = $this->getDoctrine()
->getEntityManager();
$repo = $this->getDoctrine()
->getRepository('NatknowEditorBundle:Article');
$success = "<h3>Use this form to add an article:</h3>";
$form = $this->createForm(new ArticleType(), $art);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($art);
$em->flush();
$success = "You have successfully added the article '"
. $art->getName() . "'!";
$articles = $repo->findAllPastDay();
}else {
$success = "There was an error validating the form data!";
}
return $this->render('NatknowEditorBundle:Default:insertArticle.html.php',
array('form' => $form->createView(), 'status' => $success, 'arts' => $articles,)
);
}
[...]
Heads-up: I used the command line utility to generate the ArticleCategory.php entity, without error. However, I'm not 100% certain it's set up to do what I would like.
You need to add a setCatagories() to the Article entity to get past the posted error.
Could run into other issues. Getting many-many forms to work as desired can be tricky.
Become very familiar with:
http://symfony.com/doc/current/cookbook/form/form_collections.html
You should name addArticleCategory() as addCategory(), then Symfony (master) will recognize it just fine.
Don't forget about using:
Doctrine\Common\Collections\ArrayCollection;
and:
public function __construct()
{
$this->categories = new ArrayCollection();
}
(Article.php)
Not sure if this was the problem, but I just ran into something similar.