Magento 2 Create Shipping Method with Delivery Options - magento-2.0

I created a new shipping method for home delivery and I want to be able to present options such as a building/unit/room number. My thought was when the user selected this method the options would appear with a text field for the user to enter information before moving to the payment page. Any guidance on the best way to make this happen?
This is in Model/Carrier
/**
* #param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* #param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
* #param \Psr\Log\LoggerInterface $logger
* #param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
* #param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
* #param array $data
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
array $data = []
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
$this->_logger = $logger;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
/**
* #param RateRequest $request
* #return \Magento\Shipping\Model\Rate\Result|bool
*/
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
/** #var \Magento\Shipping\Model\Rate\Result $result */
$result = $this->_rateResultFactory->create();
$shippingPrice = $this->getConfigData('price');
$method = $this->_rateMethodFactory->create();
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($this->_code);
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$result->append($method);
return $result;
}
/**
* #return array
*/
public function getAllowedMethods()
{
return [$this->_code=> $this->getConfigData('name')];
}
I tried to create checkout_index_index.xml and add a custom phtml page to it with
<script type="text/javascript">
require([
'jquery',
'Magento_Checkout/js/model/quote',
], function (jQuery, quote) {
jQuery(document).ready(function () {
quote.shippingMethod.subscribe(function (value) {
if (quote.shippingMethod() && quote.shippingMethod().carrier_code == 'your_custom_shipping_method_code') {
var customBlock = "<div class ='custom-information'><input type="text" id="your_custom_id"></div>";
if((!$('.custom-information').length > 0)) {
$('#checkout-shipping-method-load').append(customBlock);
}
});
});
});
});
</script>
And then I added in Model
namespace Magento\Checkout\Model;
class GuestShippingInformationManagement implements \Magento\Checkout\Api\GuestShippingInformationManagementInterface
{
/**
* #var \Magento\Quote\Model\QuoteIdMaskFactory
*/
protected $quoteIdMaskFactory;
/**
* #var \Magento\Checkout\Api\ShippingInformationManagementInterface
*/
protected $shippingInformationManagement;
/**
* #param \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory
* #param \Magento\Checkout\Api\ShippingInformationManagementInterface $shippingInformationManagement
* #codeCoverageIgnore
*/
public function __construct(
\Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory,
\Magento\Checkout\Api\ShippingInformationManagementInterface $shippingInformationManagement
) {
$this->quoteIdMaskFactory = $quoteIdMaskFactory;
$this->shippingInformationManagement = $shippingInformationManagement;
}
/**
* {#inheritDoc}
*/
public function saveAddressInformation(
$cartId,
\Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation
) {
/** #var $quoteIdMask \Magento\Quote\Model\QuoteIdMask */
$quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id');
return $this->shippingInformationManagement->saveAddressInformation(
$quoteIdMask->getQuoteId(),
$addressInformation
);
}
}
and started to modify it but I think I may be headed in the wrong direction,
Thoughts on the best way to accomplish this?
Thanks!

Related

Symfony 4 with Doctrine - save ManyToOne

I have problem with my symfony code:
My repository update method
/**
* #param MenuModel $menu
* #return MenuEntity|MenuModel
* #throws RepositoryException
*/
public function updateMenu(MenuModel $menu)
{
try {
$transformedMenu = $this->menuTransformer->transform($menu);
$transformedMenu = $this->getEntityManager()->merge($transformedMenu);
$this->getEntityManager()->flush($transformedMenu);
$this->getEntityManager()->detach($transformedMenu);
return $this->menuTransformer->transform($transformedMenu);
} catch (\Exception $e) {
throw new RepositoryException($e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
}
}
My Element entity:
/**
* Element.
*
* #ORM\HasLifecycleCallbacks
* #ORM\Table(name="element")
* #ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
* #ORM\Entity(repositoryClass="CP\API\Repository\ElementRepository")
*/
class Element extends \CP\RestBundle\Model\Element
{
use Traits\SystemObjectTrait;
use Traits\ChannelsTrait;
use Traits\PropertiesTrait;
use Traits\WorkflowTrait;
/**
* #ORM\ManyToOne(targetEntity="Menu", inversedBy="contents")
* #ORM\JoinColumn(name="menu_id", referencedColumnName="id")
*/
protected $menu;
/**
* Element constructor.
*/
public function __construct()
{
parent::__construct();
}
/**
* #param int $id
*
* #return Element
*/
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
/**
* Update publication by modification when empty
* Update status according to publication, unpublication and archiving
*
* #ORM\PrePersist()
*/
protected function prePersist()
{
$this->updatePublication();
$this->updateStatus();
}
/**
* Update publication by modification when empty
* Update status according to publication, unpublication and archiving
*
* #ORM\PreUpdate()
*/
public function preUpdate()
{
$this->updatePublication();
$this->updateStatus();
}
/**
* Increases object version
*/
public function increaseVersion()
{
++$this->version;
}
/**
* #return mixed
*/
public function getMenu()
{
return $this->menu;
}
/**
* #param mixed $menu
*/
public function setMenu($menu): void
{
$this->menu = $menu;
}
}
My Menu entity
<?php
namespace CP\API\Entity;
use CP\API\Entity\Traits\TimestampableTrait;
use CP\Model\Configuration;
use CP\Model\Content;
use CP\Model\Language;
use CP\Model\MenuTranslation;
use CP\RestBundle\Model\Locator;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\HasLifecycleCallbacks()
* #ORM\Table(name="custom_menu")
* #ORM\Entity(repositoryClass="CP\API\Repository\MenuRepository")
*/
class Menu
{
use TimestampableTrait;
/**
* #var int
*
* #ORM\Id()
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="CP\API\Entity\Element",mappedBy="menu",cascade={"persist"})
*/
protected $contents;
public function __construct(Menu $parent = null)
{
$dateTime = new \DateTime();
$this->creation = $dateTime;
$this->modification === null && $this->setModification($dateTime);
$this->contents = new ArrayCollection();
}
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* #return ArrayCollection
*/
public function getContents(): ArrayCollection
{
return $this->contents;
}
/**
* #param ArrayCollection $contents
*/
public function setContents(ArrayCollection $contents): void
{
$this->contents = $contents;
}
/**
* #param Element $element
* #return $this
*/
public function addContent(Element $element): self
{
if (!$this->contents->contains($element)) {
$this->contents[] = $element;
$element->setMenu($this);
}
return $this;
}
/**
* #param Element $element
* #return $this
*/
public function removeContent(Element $element): self
{
if ($this->contents->contains($element)) {
$this->contents->removeElement($element);
if ($element->getMenu() === $this) {
$element->setMenu(null);
}
}
return $this;
}
}
My menu model
<?php
namespace CP\Model;
use CP\RestBundle\Model\Element;
use CP\RestBundle\Model\Locator;
use CP\RestBundle\Model\Product;
use CP\RestBundle\Model\Traits\TimestampableTrait;
class Menu extends BaseModel
{
/** #var Content[] */
protected $content;
/**
* #return array|null
*/
public function getContent(): ?array
{
return $this->content;
}
/**
* #param Content[] $content
*/
public function setContent(array $content): void
{
$this->content = $content;
}
}
My transformer from model to entity
public function transform($object)
{
if ($object instanceof Menu) {
$menuData = new MenuEntity();
if ($object->getId())
$menuData->setId($object->getId());
if ($object->getContent() instanceof Content) {
$contentEntity = new ContentEntity();
$content = $object->getContent();
$contentEntity->setId($content->getId());
$menuData->addContent($this->attachToEntityManager($contentEntity));
}
return $menuData;
}
private function attachToEntityManager($object)
{
try {
$attachedObject = $this->entityManager->merge($object);
return $attachedObject;
} catch (ORMException $e) {
throw new ModelTransformationException(sprintf('Model transformation error, object could not be attached to Entity Manager: %s in %s',
$e->getMessage(), $e->getFile() . ':' . $e->getLine()));
}
}
When i try saved data then i don't have any error, but on database nothing change i.e. element entity don't have assign menu_id from relation. I don't know what is wrong, maybe i don't know how to use and save OneToMany relation.
Any idea?
Can you give us more context of what your code is doing ? The constructor of MenuEntity is strange, no use of $parent, a boolean comparaison isn't used. Why do you need to use detach and merge methods of entityManager
- Mcsky
Is right, I don't see the point of using detach and/or merge here.
Normally with a OneToMany relationship you use entity manager and persist both relations, flush and you should have an entity with a OneToMany relationship.
I hope this might be helpful, specifically this part: https://symfony.com/doc/current/doctrine/associations.html#saving-related-entities
example:
// relates this product to the category
$product->setCategory($category);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($category);
$entityManager->persist($product);
$entityManager->flush();

How to create url signature on the place of parameters in laravel 5.4

It just my thought i just want to do like the same, I haven't try this because of i haven't any idea about this means how it will be done.
For Example:
I have - mysite.com/view?user_id=12 , I don't want to show url's parameters (?user_id=12) on url, On the place of this, I want to show like
mysite.com/view?_signature=encryptedparameter
(like : mysite.com/view?_signature=853ef7a0ff5aea6f24152b1d1ed4d771)
853ef7a0ff5aea6f24152b1d1ed4d771 will denotes user_id=12.
If i have multiple parameters it would be like the same and i will have a single encrypted string and i will get all parameters with that string.
Yes but i am using in Laravel 5.1
assume if i have "mysite.com/view?user_id=12"
And i want "mysite.com/view?_signature=encryptedparameter"
Please fallow some steps
laravel>packages>myfolder>core
+=>folder
-=>file
+packages
+Folder
+core
+src
+Faundation
-Application.php
+Routing
-RoutingServiceProvider.php
-UriGenerator.php
+Support
+Middleware
-UrlParamRevealerMiddleware.php
+ServiceProvider
-CoreServiceProvider.php
-UriParamProtector.php
<<IN APPLICATION.PHP>>
<?php
namespace Folder\Core\Foundation;
use Illuminate\Events\EventServiceProvider;
use Folder\Core\Routing\RoutingServiceProvider;
use Illuminate\Foundation\Application as BaseApplication;
use Folder\Core\Support\ServiceProvider\CoreServiceProvider;
class Application extends BaseApplication
{
/**
* Register all of the base service providers.
*
* #return void
*/
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new CoreServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
}
<<//IN APPLICATION.PHP>>
<<-RoutingServiceProvider>>
<?php
namespace Folder\Core\Routing;
use Folder\Core\Routing\UrlGenerator;
use Illuminate\Routing\RoutingServiceProvider as BaseServiceProvider;
class RoutingServiceProvider extends BaseServiceProvider
{
/**
* Register the URL generator service.
*
* #return void
*/
protected function registerUrlGenerator()
{
$this->app['url'] = $this->app->share(function ($app) {
$routes = $app['router']->getRoutes();
// The URL generator needs the route collection that exists on the router.
// Keep in mind this is an object, so we're passing by references here
// and all the registered routes will be available to the generator.
$app->instance('routes', $routes);
$url = $this->getUrlGenerator($routes);
$url->setSessionResolver(function () {
return $this->app['session'];
});
// If the route collection is "rebound", for example, when the routes stay
// cached for the application, we will need to rebind the routes on the
// URL generator instance so it has the latest version of the routes.
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
}
/**
* Get the url generator instance.
*
* #param \Illuminate\Routing\RouteCollection $routes
* #return \Folder\Core\Routing\UrlGenerator
*/
protected function getUrlGenerator($routes)
{
$url = new UrlGenerator(
$routes,
$this->app->rebinding(
'request',
$this->requestRebinder()
)
);
return $url;
}
}
<</-RoutingServiceProvider>>
<<UriGenerator.php>>
<?php
namespace Folder\Core\Routing;
use ErrorException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\UrlGenerator as BaseUrlGenerator;
class UrlGenerator extends BaseUrlGenerator
{
/**
* Get the URL to a named route.
*
* #param string $name
* #param mixed $parameters
* #param bool $absolute
* #return string
*
* #throws \InvalidArgumentException
*/
public function route($name, $parameters = [], $absolute = true)
{
$encryptedParameters = $parameters;
if (Auth::guest() === false) {
$encryptedParameters = $this->encrypt($name, $parameters);
}
return parent::route($name, $encryptedParameters, $absolute);
}
/**
* Get the cryptic engine.
*
* #return \Folder\Core\Support\UrlParamEncrypter
*
* #throws \ErrorException
*/
protected function getCrypt()
{
$app = App::getInstance();
if (isset($app['urlencryptor'])) {
return $app['urlencryptor'];
}
throw new ErrorException('URL Encryptor was not found.');
}
/**
* Get the protector engine.
*
* #return #return \Folder\Core\Support\UrlParamProtector
*
* #throws \ErrorException
*/
protected function getProtector()
{
$app = App::getInstance();
if (isset($app['urlprotector'])) {
return $app['urlprotector'];
}
throw new ErrorException('URL Protector was not found.');
}
/**
* Encrypts the parameter passed as querystring in URL.
*
* #param array $parameters
* #return array
*/
protected function encrypt($routeName, $parameters = [])
{
if (! is_array($parameters)) {
return $parameters;
}
if (count($parameters) === 0) {
return [];
}
if (Auth::guest() === true) {
return $parameters;
}
$protected = $this->getProtector()->protect($routeName, $parameters);
return ['__signature' => $protected];
}
}
<<//UriGenerator.php>>
<<UrlParamRevealerMiddleware.php>>
<?php
namespace Folder\Core\Support\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Folder\Core\Support\UrlParamProtector;
class UrlParamRevealerMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
(! Auth::guest()) && App::make(UrlParamProtector::class)->reveal($request);
return $next($request);
}
}
<<//UrlParamRevealerMiddleware.php>>
<<CoreServiceProvider.php>>
<?php
namespace Folder\Core\Support\ServiceProvider;
use Illuminate\Support\ServiceProvider;
use Folder\Core\Support\UrlParamProtector;
class CoreServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->app->make('Illuminate\Contracts\Http\Kernel')
->pushMiddleware('Folder\Core\Support\Middleware\UrlParamRevealerMiddleware');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerUrlProtector();
}
/**
* Register UrlProtector class.
*/
protected function registerUrlProtector()
{
$this->app->singleton('urlprotector', function () {
return new UrlParamProtector();
});
}
}
<<//CoreServiceProvider.php>>
<<-UriParamProtector.php>>
<?php
namespace Folder\Core\Support;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class UrlParamProtector
{
/**
* Session key.
*
* #var string
*/
protected $sessionKey = '__url_protector__';
/**
* Request class.
*
* #var \Illuminate\Http\Request
*/
protected $request;
/**
* Values those needs to be merged in request object.
*
* #var array
*/
protected $valuesToBeMerged;
/**
* Create and returns VALID RFC 4211 COMPLIANT
* Universally Unique IDentifiers (UUID) version 4.
*
* #return string
*/
protected function getNewGuid()
{
if (function_exists('com_create_guid') === true) {
return trim(com_create_guid(), '{}');
}
return sprintf(
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(16384, 20479),
mt_rand(32768, 49151),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535)
);
}
/**
* Create the route key.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
protected function getRouteKey($routeName, array $parameters = [])
{
if (count($parameters) <= 0) {
$paramToString = '';
} else {
$paramToString = implode('-', array_map(
function ($k, $v) {
return $k . '-' . $v;
},
array_keys($parameters),
array_values($parameters)
));
}
$routeKey = 'route__' . $routeName . (empty($paramToString) ? '' : '-' . $paramToString);
return $routeKey;
}
/**
* Returns a GUID for a URL parameter.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
public function protect($routeName, array $parameters)
{
$routeKey = $this->getRouteKey($routeName, $parameters);
if (Session::has($this->sessionKey . '.' . $routeKey) === false) {
$guid = Str::lower($this->getNewGuid());
Session::set($this->sessionKey . '.' . $routeKey, [
'guid' => $guid,
'loggedin_user_id' => (Auth::guest() ? 0 : Auth::user()->id),
'params' => $parameters,
]);
} else {
$guid = Session::get($this->sessionKey . '.' . $routeKey . '.guid');
}
return $guid;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
protected function isValidGuid($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if (!isset($value['guid'])) {
list($innerKey, $val) = each($value);
} else {
$val = $value;
}
if ($val['guid'] === $guid) {
$this->valuesToBeMerged = $val['params'];
return true;
}
}
return false;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
public function isValidGuidForPost($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if ($value['guid'] === $guid && Auth::user()->id === $value['loggedin_user_id']) {
$this->valuesToBeMerged = $value['params'];
return true;
}
}
return false;
}
/**
* Merge the request with our revealed values.
*/
protected function mergeRequest()
{
$this->request->merge($this->valuesToBeMerged);
}
/**
* Check whether a "__signature" is correct or not.
*
* #param \Illuminate\Http\Request $request
* #return boolean
*/
public function reveal(Request &$request)
{
$this->request = $request;
$guid = ($this->request->query('__signature') ? : false);
if ($guid === false) {
return false;
}
if ($this->isValidGuid($guid) === false) {
App::abort(400);
}
$this->mergeRequest();
}
}
<<//-UriParamProtector.php>>
==============================================
after that in "bootstrap>App.php"
use this=>
$app = new Folder\Core\Foundation\Application(
realpath(__DIR__.'/../')
);
instad of =>
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
in any link use "data-href"
<a data-href="route('modify_lead_status',['user_id' => $users->id])" href="javascript:void(0)"><i class=\"fa fa-random\"></i></a>"
and after that any controller,Routing,middleware will be same.....
>>composer auto-dump
<<Please check spealing be sure use same>>
i hope this is help full....thanks

Get maximum id inside Doctrine entity

I need to get maximum ID of a table inside of symfony 2.7 entity. But instead of having the id I'm getting this issue.
Notice: Undefined property: AppBundle\Entity\BlogPost::$container
This is my BlogPost entity,
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* BlogPost
*
* #ORM\Table()
* #ORM\Entity
*/
class BlogPost {
const SERVER_PATH_TO_IMAGE_FOLDER = '/uploads';
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="body", type="text")
*/
private $body;
/**
* #var string
*
* #ORM\Column(name="filename", type="text")
*/
private $filename;
/**
* Set filename
*
* #param string $filename
* #return BlogPost
*/
public function setFilename($filename) {
$this->filename = $filename;
return $this;
}
public function setUploader(UploadedFile $file) {
$em = $this->container->get('doctrine.orm.entity_manager');
$highest_id = $em->createQueryBuilder()
->select('MAX(b.id)')
->from('AppBundle:BlogPost', 'b')
->getQuery()
->getSingleScalarResult();
var_dump($highest_id);
exit();// exit for check value
$url = 'uploads/events';
$file_name = 'fsdf.' . $file->guessExtension();
$file->move($url, $file_name);
}
/**
* Get filename
*
* #return string
*/
public function getFilename() {
return $this->filename;
}
/**
* #var boolean
*
* #ORM\Column(name="draft", type="boolean")
*/
private $draft;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return BlogPost
*/
public function setTitle($title) {
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle() {
return $this->title;
}
/**
* Set body
*
* #param string $body
* #return BlogPost
*/
public function setBody($body) {
$this->body = $body;
return $this;
}
/**
* Get body
*
* #return string
*/
public function getBody() {
return $this->body;
}
/**
* Set draft
*
* #param boolean $draft
* #return BlogPost
*/
public function setDraft($draft) {
$this->draft = $draft;
return $this;
}
/**
* Get draft
*
* #return boolean
*/
public function getDraft() {
return $this->draft;
}
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="blogPosts")
*/
private $category;
public function setCategory(Category $category) {
$this->category = $category;
}
public function getCategory() {
return $this->category;
}
/**
* Unmapped property to handle file uploads
*/
public $file;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null) {
$this->file = $file;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile() {
return $this->file;
}
/**
* Manages the copying of the file to the relevant place on the server
*/
public function upload() {
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
// we use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and target filename as params
$this->getFile()->move(
self::SERVER_PATH_TO_IMAGE_FOLDER, $this->getFile()->getClientOriginalName()
);
// set the path property to the filename where you've saved the file
$this->filename = $this->getFile()->getClientOriginalName();
// clean up the file property as you won't need it anymore
$this->setFile(null);
}
/**
* Lifecycle callback to upload the file to the server
*/
public function lifecycleFileUpload() {
$this->upload();
}
/**
* Updates the hash value to force the preUpdate and postUpdate events to fire
*/
public function refreshUpdated() {
// $this->setUpdated(new \DateTime());
}
// ... the rest of your class lives under here, including the generated fields
// such as filename and updated
}
This is the part I'm trying to get max id,
public function setUploader(UploadedFile $file) {
$em = $this->container->get('doctrine.orm.entity_manager');
$highest_id = $em->createQueryBuilder()
->select('MAX(b.id)')
->from('AppBundle:BlogPost', 'b')
->getQuery()
->getSingleScalarResult();
var_dump($highest_id);
exit();// exit for check value
$url = 'uploads/events';
$file_name = 'fsdf.' . $file->guessExtension();
$file->move($url, $file_name);
}
With the help of comments and few research I figured out the issue is in 'entity_manager' part. Is there a way to call doctrine queries inside Entity?
If I were you, i would do something like that :
Controller:
$blogPost= new BlogPost () ;
$em = $this->getDoctrine()->getManager();
//..your code
// I assume you want to do that after a form post
$blogPost = $form->getData();
$id = $em->getRepository('AppBundle:BlogPost')->getMaxId();
$blogPost->setUploader($id);
//...
Repository:
public function getMaxId()
{
$qb = $this->createQueryBuilder('u');
$qb->select('u, MAX(id) as idMax');
return $qb->getQuery()->getSingleResult();
}
Entity:
public function setUploader(UploadedFile $file, $id)
{
var_dump($id);
$url = 'uploads/events';
$file_name = 'fsdf.'.$id.$file->guessExtension();
$file->move($url, $file_name);
}
It should work
I would suggest to hold the EntityManager as a class variable inside your Entity and either instantiate it via the constructor or via a setter-method which you call before you use the setUploader function.
This should be the cleanest and best readable solution.
Form another thread I found this and it's working for me.
global $kernel;
if ( 'AppCache' == get_class($kernel) )
{
$kernel = $kernel->getKernel();
}
$em = $kernel->getContainer()->get( 'doctrine.orm.entity_manager');
I can't use it in controller cause I have an admin class instead of controller on this. Since lot of people suggesting this using entity_manager inside entity is not good practice I'm using the code inside admin class instead of entity.
This is the original thread..
How to use entityManager inside Entity?
Try this in your Controller:
$blogPost= new BlogPost () ;
$em = $this->getDoctrine()->getManager();
$blogPost = $form->getData();
$maxId = $em->getRepository('AppBundle:BlogPost')->createQueryBuilder('b')
->where("MAX(b.id) as maxId")
->getQuery()
->getSingleResult();

Symfony2 DoctrineBehaviors, JordiLlonchCrudGeneratorBundle, LexikFormFilterBundle issue

I use DoctrineBehaviors to apply translation of my entity, and JordiLlonchCrudGenerator to generate my crud, and LexikFormFilterBundle to generate my form filters type.
My form type
class PageFilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'filter_text')
->add('content', 'filter_text')
;
$listener = function(FormEvent $event)
{
// Is data empty?
foreach ($event->getData() as $data) {
if(is_array($data)) {
foreach ($data as $subData) {
if(!empty($subData)) return;
}
}
else {
if(!empty($data)) return;
}
}
$event->getForm()->addError(new FormError('Filter empty'));
};
$builder->addEventListener(FormEvents::POST_BIND, $listener);
}
When i try to filters my entities, the error said hat no field called title in Class Entity\Page.
I understand this problem but i have no idea how to resolve this error, because the field title is into the entity PageTranslation, here my function filters :
protected function filter()
{
$request = $this->getRequest();
$session = $request->getSession();
$filterForm = $this->createForm(new PageFilterType());
$em = $this->getDoctrine()->getManager();
$queryBuilder = $em->getRepository('PageBundle:Page')
->createQueryBuilder('e')
->select('e')
->where('e.deletedAt IS NULL')
;
// Reset filter
if ($request->get('filter_action') == 'reset') {
$session->remove('PageControllerFilter');
}
// Filter action
if ($request->get('filter_action') == 'filter') {
// Bind values from the request
$filterForm->bind($request);
if ($filterForm->isValid()) {
// Build the query from the given form object
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($filterForm, $queryBuilder);
// Save filter to session
$filterData = $filterForm->getData();
$session->set('PageControllerFilter', $filterData);
}
} else {
// Get filter from session
if ($session->has('PageControllerFilter')) {
$filterData = $session->get('PageControllerFilter');
$filterForm = $this->createForm(new PageFilterType(), $filterData);
$this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($filterForm, $queryBuilder);
}
}
return array($filterForm, $queryBuilder);
}
I think that i should customize this line but i don't know how
$queryBuilder = $em->getRepository('PageBundle:Page')
->createQueryBuilder('e')
->select('e')
->where('e.deletedAt IS NULL')
;
Any solution for that ?
Also, i have created a trash for each entity, for exemple if one page is deleted the user can find it on trash,
Exemple : http://snapplr.com/snap/xxmk
So i have no problem with the action restore all, but remove all is not functional
This is my action
public function emptyTrashAction(){
$em = $this->getDoctrine()->getEntityManager();
$entities=$em->getRepository('PageBundle:Page')->findByRemoved();
if($entities){
foreach ($entities as $entity) {
$em->remove($entity);
$em->flush();
}
$this->get('session')->getFlashBag()->add('success', 'La corbeille est vide !!');
return $this->redirect($this->generateUrl('pa_trash'));
}else{
$this->get('session')->getFlashBag()->add('error', 'La corbeille est déjà vide !! ');
return $this->redirect($this->generateUrl('pa'));
}
}
What i wanna do, is to delete all entities where the feild DeletedAt is not empty, how can i do this ?
Thanks //
This is my entity Page Class
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* Page
* #ORM\Table(name="page")
* #ORM\Entity(repositoryClass="Core\PageBundle\Entity\PageRepository")
*
*/
class Page
{
use ORMBehaviors\Translatable\Translatable;
use ORMBehaviors\Timestampable\Timestampable;
use ORMBehaviors\SoftDeletable\SoftDeletable;
use ORMBehaviors\Blameable\Blameable;
public function __call($method, $arguments)
{
return \Symfony\Component\PropertyAccess\PropertyAccess::createPropertyAccessor()->getValue($this->translate(), $method);
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="nbview", type="integer", nullable=true)
*/
private $nbview;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nbview
*
* #param integer $nbview
* #return Page
*/
public function setNbview($nbview)
{
$this->nbview = $nbview;
return $this;
}
/**
* Get nbview
*
* #return integer
*/
public function getNbview()
{
return $this->nbview;
}
public function getUpdateLogMessage(array $changeSets = [])
{
return 'Changed: '.print_r($changeSets, true);
}
public function getRemoveLogMessage()
{
return 'removed!';
}
And this is the translation page class
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Table(name="page_lang")
* #ORM\Entity()
*/
class PageTranslation
{
use ORMBehaviors\Translatable\Translation;
use ORMBehaviors\Sluggable\Sluggable;
/**
* #inheritdoc
*/
public function getSluggableFields()
{
return ['title'];
}
/**
* #inheritdoc
*/
public function getSlug()
{
if (!$this->slug) {
$this->generateSlug();
}
return $this->slug;
}
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var string $content
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #var string $meta
*
* #ORM\Column(name="meta", type="text", nullable=true)
*/
private $meta;
public function getId(){
return $ths->id;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set title
*
* #param string $title
* #return Page
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Set content
*
* #param string $content
* #return Page
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* #param $method
* #param $args
*
* #return mixed
*/
/**
* Set meta
*
* #param string $meta
* #return PageTranslation
*/
public function setMeta($meta)
{
$this->meta = $meta;
return $this;
}
/**
* Get meta
*
* #return string
*/
public function getMeta()
{
return $this->meta;
}
}

LifecycleCallbacks are not executed in Symfony2

I am having problem with LifecycleCallbacks in symfony2 not being executed even though I have #ORM\HasLifecycleCallbacks annotation. I am trying to follow example provided in http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html#using-the-id-as-the-filename. My goal is to save file under the document id.
The below provided code does not result in an error, other than the
The file could not be found. information in reloaded page.
To check what is going on I added die("TEST"); command to upload() function but it seems that it is never executed as the result was only the form page being reloaded with the above mentioned error.
I would like to ask you for advice what may be the reason that the upload() function is not executed?
Controller:
/**
* #Route("app/documents/add/", name="app_documents_add")
*/
public function addAction(Request $request)
{
/**
* This code is aimed at checking if the book is choseen and therefore whether any further works may be carried out
*/
$session = new Session();
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->generateUrl('app_listbooks'));
// Authorization goes here
$documents = new Documents();
$form = $this->createForm(new DocumentsType(), $documents);
$form->add('save', 'submit', array('label' => 'Dodaj dokument'));
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
//$documents->upload();
$book = $em->getReference('AppBundle:Books', $session->get("App_Books_Chosen_Lp"));
if( $book ) $documents->setBook($book);
else die ("CRITICAL ERROR: addAction - Bad book id");
$em->persist($documents);
$em->flush();
}
return $this->render('AppBundle:Documents:adddocuments.html.twig', array('form' => $form->createView()));
}
Documents class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
* #ORM\Table(name="Documents")
*/
class Documents
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Books", inversedBy="documents")
* #ORM\JoinColumn(name="book_id", referencedColumnName="id")
*/
protected $book;
/**
* #ORM\Column(type="string", length=220)
*/
protected $marker;
/**
* #ORM\Column(type="date", length=220)
*/
protected $document_date;
/**
* #ORM\Column(type="string", length=220)
* #Assert\File(maxSize="6000000")
*/
protected $link;
/**
* #ORM\Column(type="text")
*/
protected $notes;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set marker
*
* #param string $marker
* #return Documents
*/
public function setMarker($marker)
{
$this->marker = $marker;
return $this;
}
/**
* Get marker
*
* #return string
*/
public function getMarker()
{
return $this->marker;
}
/**
* Set document_date
*
* #param \DateTime $documentDate
* #return Documents
*/
public function setDocumentDate($documentDate)
{
$this->document_date = $documentDate;
return $this;
}
/**
* Get document_date
*
* #return \DateTime
*/
public function getDocumentDate()
{
return $this->document_date;
}
/**
* Set link
*
* #param string $link
* #return Documents
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* Get link
*
* #return string
*/
public function getLink()
{
return $this->link;
}
/**
* Set notes
*
* #param string $notes
* #return Documents
*/
public function setNotes($notes)
{
$this->notes = $notes;
return $this;
}
/**
* Get notes
*
* #return string
*/
public function getNotes()
{
return $this->notes;
}
/**
* Set book
*
* #param \AppBundle\Entity\Books $book
* #return Documents
*/
public function setBook(\AppBundle\Entity\Books $book = null)
{
$this->book = $book;
return $this;
}
/**
* Get book
*
* #return \AppBundle\Entity\Books
*/
public function getBook()
{
return $this->book;
}
/*
* ### FILE UPLOAD PROCESS ###
*/
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
public function getWebPath()
{
return null === $this->link
? null
: $this->getUploadDir().'/'.$this->link;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploads/documents';
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
/*
* Temp fila path
*/
private $temp;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
// check if we have an old image path
if (is_file($this->getAbsolutePath())) {
// store the old name to delete after the update
$this->temp = $this->getAbsolutePath();
} else {
$this->link = 'initial';
}
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->getFile()) {
$this->link = $this->getFile()->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->getFile()) {
return;
}
// check if we have an old image
if (isset($this->temp)) {
// delete the old image
unlink($this->temp);
// clear the temp image path
$this->temp = null;
}
// you must throw an exception here if the file cannot be moved
// so that the entity is not persisted to the database
// which the UploadedFile move() method does
$this->getFile()->move(
$this->getUploadRootDir(),
$this->id.'.'.$this->getFile()->guessExtension()
);
$this->setFile(null);
}
/**
* #ORM\PreRemove()
*/
public function storeFilenameForRemove()
{
$this->temp = $this->getAbsolutePath();
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if (isset($this->temp)) {
unlink($this->temp);
}
}
public function getAbsolutePath()
{
return null === $this->link
? null
: $this->getUploadRootDir().'/'.$this->id.'.'.$this->link;
}
}
`
The answer why the upload() function was not executed was quite easy - the form is marked as invalid. Now I am looking for help why this happens (The file could not be found while using LifecycleCallbacks)

Resources