Is there a clean way to give the user ability to retry payment if the attempt after placing order failed in Sylius 0.13?
I have frontend administration for users with list of their orders and I would like to add link to every unsuccessfully paid order that would forward user to /payment/capture/<hash> url like placing order.
Thanks.
I have resolved the problem via regular controller which handles payment itself. We have order details on frontend where payment form is visible (if unpaid):
public function showAction($number)
{
$order = $this->findOrderOr404($number);
$form = $this->getPaymentFormIfOrderPayable($order);
$view = $this
->view()
->setTemplate('SyliusWebBundle:Frontend/Account:Order/show.html.twig')
->setData(array(
'order' => $order,
'form' => $form,
))
;
return $this->handleView($view);
}
New payment has always method as last one in database. After that it generates similar form like the one after completing order.
/**
* #param OrderInterface $order
* #return bool|FormInterface form if payable otherwise false
*/
protected function getPaymentFormIfOrderPayable(OrderInterface $order) {
if($order->getState() === OrderInterface::STATE_PENDING) {
/** #var PaymentInterface $paymentMethod */
$paymentMethod = $order->getPayments()->last()->getMethod()->getGateway();
switch ($paymentMethod) {
case 'gpe':
$form = $this->createGPEPaymentRequest($order);
break;
default:
$form = false;
}
} else {
$form = false;
}
return $form;
}
After payment, user is forwarded to another action that works like CaptureAction and PaymentStatusAction in Payum:
/**
* #param Request $request
* #param string $number Order Id
* #return \Symfony\Component\HttpFoundation\RedirectResponse
* #throws NotFoundHttpException
* #throws AccessDeniedException
*/
public function payAction(Request $request, $number) {
$order = $this->findOrderOr404($number);
/** #var PaymentInterface $paymentMethod */
$paymentMethod = $order->getPayments()->last()->getMethod()->getGateway();
switch ($paymentMethod) {
case 'gpe':
$this->resolveGPEPaymentRequest($request, $order);
break;
$this->get('sylius.cart_provider')->abandonCart();
$this->get('event_dispatcher')->dispatch('sylius.checkout.purchase.complete', new PurchaseCompleteEvent($order->getPayments()->last()));
return $this->redirect($this->generateUrl('sylius_account_order_show', array('number' => $order->getNumber())));
}
Related
I am building out an interface to create a self-serve way for people to manage their Cognito IDP, but am struggling to pull through the actual data. I know I've got the foundations here but there's something I'm missing. I really need a little direction to help me get back on track.
Where it's failing is in the onPreSetData but I feel like I'm not 100% on all of the code, it's passing null through within the onPreSetData in my loginSettingsType on:
$cognitoAPIFacade = new CognitoAPIFacade();
To try work around this I was hard coding the variables but not going too well haha
it takes a bit of following but I'm certain I'm 99% there and just need a little help to get fully over the line
I'm not the most experienced coder so this is all new learning for me, any help you can provide is hugely appreciated.
I've tried adding comments to the code where it felt good to, I can clarify any areas as needed
My controller is below:
public function editAction(string $customerId, Admin $user, Request $request): Response
{
$customer = $this->validateCustomer($customerId, $user);
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = new LoginSettingsFormData($customer, $twoFactorOmniLoginFacade, $cognitoAPIFacade, $cognitoCustomerUserpoolIDP);
$form = $this->createForm(LoginSettingsType::class, $formData);
$form->handleRequest($request);
return $this->render('customer/login_settings.twig', [
'title' => $customer->getName(),
'javascript_action' => $request->attributes->get('_route'),
'form' => $form->createView(),
'page' => 'customer_login_settings',
] + $this->getTemplateParams($user, $customer));
}
/**
* #Route("", name="customer_login_settings_put", methods={"PUT"})
*
* #param Request $request
* #param Admin $user
* #param string $customerId
*
* #return Response
*
* #throws Exception
*/
public function putAction(Request $request, Admin $user, string $customerId): Response
{
$customer = $this->validateCustomer($customerId, $user);
$customerCognitoSettingsRepo = $this->getManager()->getRepository(CognitoCustomerUserPool::class);
$userPool = $customerCognitoSettingsRepo->getByCustomerID($customer->getCustomerUuid());
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = new LoginSettingsFormData($customer, $twoFactorOmniLoginFacade, $cognitoAPIFacade, $cognitoCustomerUserpoolIDP);
$form = $this->createForm(LoginSettingsType::class, $formData);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData->saveChanges($customer);
$this->addFlash('success', 'Changes saved successfully');
} else {
$this->addFlash('error', 'There was an error saving changes');
}
return $this->redirectToRoute('customer_login_settings_edit', ['customer_id' => $customerId]);
}
Login settings type:
public function buildForm(FormBuilderInterface $builder, array $options) {
---
form $builder adds
---
$builder->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'onPreSetData']);
}
public function onPreSetData(FormEvent $event, LoggerInterface $logger): void
{
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
// Both of these below are returning empty when I use VSCode breakpoints
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = $event->getData();
$form = $event->getForm();
// TODO: I was working on this but unsure where to go from here
// $cognitoCustomerUserpoolIDP = $formData->getCognitoCustomerUserpoolIDP();
if (!$formData) {
return;
}
$idpsettings = $cognitoAPIFacade->getCognitoIDPSettings($logger, $cognitoCustomerUserpoolIDP);
$customer = $formData->getCustomer();
$form = $this->createForm(LoginSettingsType::class, $formData)
---
$Builder adds
---
}
Key script from Facade I made:
public function getCognitoIDPSettings(LoggerInterface $logger, string $cognitoCustomerUserpoolIDP): array
{
$body = json_encode([
'cognito_customer_user_pool_idp_id' => $cognitoCustomerUserpoolIDP,
]);
$url = COGNITO_API_INVOKE_URL . '/idp/get';
$response = $this->postFunction($logger, $url, $body, 'application/json');
$this->checkResponseStatus($response);
$body = json_decode($response->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException("failed decoding response from cognito api");
}
return $body;
}
I separated out my form data as it was quite large:
class LoginSettingsFormData
{
private $customer;
private $twoFactorOmniLoginFacade;
private $cognitoAPIFacade;
private $cognitoCustomerUserpoolIDP;
private $ignoreUsageDeactivate;
private $twoFactorLoginApplication;
private $whitelistedIps = [];
/**
* Constructor for the class.
*
* #param CustomerEntity $customer Customer Entity object
* #param TwoFactorOmniLoginFacade $twoFactorOmniLoginFacade Two-factor omni login facade object
* #param CognitoAPIFacade $cognitoAPIFacade Cognito API facade object
* #param CognitoCustomerUserPool $cognitoCustomerUserpoolIDP Cognito customer user pool object
*/
public function __construct(
CustomerEntity $customer,
TwoFactorOmniLoginFacade $twoFactorOmniLoginFacade,
CognitoAPIFacade $cognitoAPIFacade,
CognitoCustomerUserPool $cognitoCustomerUserpoolIDP)
{
$this->customer = $customer;
$this->twoFactorOmniLoginFacade = $twoFactorOmniLoginFacade;
$this->cognitoAPIFacade = $cognitoAPIFacade;
$this->cognitoCustomerUserpoolIDP = $cognitoCustomerUserpoolIDP;
$this->ignoreUsageDeactivate = $customer->getLoginSettings()->isIgnoreUsageDeactivate();
$this->twoFactorLoginApplication = CustomerSetting::findByCustomerUuid($customer->getId())->twoFactorLoginApplication;
$this->whitelistedIps = $customer->getLoginWhitelist();
}
/**
* Submit changes made to the loggin settings
*
* #param array $formData Array of form data
* #param LoggerInterface $logger Logger to log errors
*/
public function submit(array $formData, LoggerInterface $logger)
{
// Check if idp is set
if (null !== $this->idp && 'none' === $formData['idp_type']) {
// Delete the Cognito IDP settings with the provided logger and idp
$this->cognitoAPIFacade->deleteCognitoIDPSettings($logger, $this->idp);
// exit early
return;
}
if ('none' !== $formData['idp_type']) {
// Create a user pool with the provided form data and logger
// TODO:: consider handle exceptions?
$this->cognitoAPIFacade->createUserPool($logger, $formData);
}
}
/**
* Update the identity provider for the loggin settings
*
* #param CognitoAPIFacade $cognitoAPIFacade
* #param CognitoAPIFacade $userpool
* #param Logger $logger Logger to log errors
*/
public function updateIdentityProvider(CognitoAPIFacade $cognitoAPIFacade, $userpool, Logger $logger): void
{
// Assign the user pool value from the cognitoAPIFacade
$userPool = $cognitoAPIFacade->getUserPool();
// log error message if the user pool is null
if (null === $userPool) {
$logger->error("User pool is null, please check the configuration");
return;
}
// Store provider for quick reference
$idp = $userPool->getIdentityProvider();
// If the selected identityprovider is null
if (null === $idp) {
// Check if the form data specifies to set the identityprovider to "none"
if ($this->idpType !== 'none' && $this->active) {
// Otherwise, create a new identityprovider using the form data
$cognitoAPIFacade->createUserPool($logger, $this);
}
return;
}
// Check if the form data specifies to set the identityprovider to "none"
if ($this->idpType === 'none') {
// If so, delete the existing identityprovider settings
$cognitoAPIFacade->deleteCognitoIDPSettings($logger, $idp);
return;
}
// If the form data specifies a different identity provider than the current one
if ($idp->getCognitoIDPSettings() !== $this->idpType
&& ($this->idpType === "SAML" || $this->idpType === "Google")
&& $idp->getCognitoIDPSettings() === "none") {
// Delete the existing identityprovider settings and create a new user pool using the form data
$cognitoAPIFacade->deleteCognitoIDPSettings($logger, $idp);
$cognitoAPIFacade->createUserPool($logger, $this);
}
}
/**
* Save changes made to the object to the database
*
* #return bool Returns true if the changes were saved successfully, false otherwise
*/
public function saveChanges(CustomerEntity $customer)
{
// Set the ignore usage deactivate flag in the customer's login settings
$this->customer->getLoginSettings()->setIgnoreUsageDeactivate($this->ignoreUsageDeactivate);
// Clear the current whitelist of IP addresses for the customer's login settings
$this->customer->getLoginWhitelist()->clear();
// Add each IP address to the whitelist in the customer's login settings
foreach ($this->whitelistedIps as $ip) {
$this->customer->getLoginWhitelist()->add($ip);
}
// Save the changes to the customer object
$this->customer->save();
}
/**
* Set whether to ignore usage deactivation
*
* #param bool $ignoreUsageDeactivate true to ignore usage deactivation, false otherwise
*/
public function setIgnoreUsageDeactivate(bool $ignoreUsageDeactivate)
{
$this->ignoreUsageDeactivate = $ignoreUsageDeactivate;
}
/**
* Bool check whether usage deactivation is ignored
*
* #return bool true if usage deactivation is ignored, false otherwise
*/
public function isIgnoreUsageDeactivate(): bool
{
return $this->ignoreUsageDeactivate;
}
/**
* Set the two factor login application
*
* #param mixed $twoFactorLoginApplication the two factor login application
*/
public function setTwoFactorLoginApplication($twoFactorLoginApplication)
{
$this->twoFactorLoginApplication = $twoFactorLoginApplication;
}
/**
* Get the two factor login application
*
* #return mixed the two factor login application
*/
public function getTwoFactorLoginApplication()
{
return $this->twoFactorLoginApplication;
}
/**
* Set the customer entity
*
* #param CustomerEntity $customer the customer entity
*/
public function setCustomer(CustomerEntity $customer)
{
$this->customer = $customer;
}
/**
* Get the customer entity
*
* #return CustomerEntity the customer entity
*/
public function getCustomer(): CustomerEntity
{
return $this->customer;
}
/**
* Set the whitelisted IP addresses
*
* #param array $whitelistedIps the array of whitelisted IP addresses
*/
public function setWhitelistedIps(array $whitelistedIps)
{
$this->whitelistedIps = $whitelistedIps;
}
/**
* Get the array of whitelisted IP addresses
*
* #return array the array of whitelisted IP addresses
*/
public function getWhitelistedIps(): array
{
return $this->whitelistedIps;
}
/**
* Get the two factor applications
*
* #return mixed the two factor applications
*/
public function getTwoFactorApplications()
{
return $this->twoFactorOmniLoginFacade->findTwoFactorApplications($this->customer);
}
/**
* Get the two factor login setting
*
* #return mixed the two factor login setting
*/
public function getTwoFactorLoginSetting()
{
return $this->twoFactorOmniLoginFacade->findTwoFactorLoginSetting($this->customer->getId());
}
/**
* Get the Cognito IDP settings
*
* #return mixed the Cognito IDP settings
*/
public function getCognitoIDPSettings()
{
return $this->cognitoAPIFacade->getCognitoIDPSettings($this->cognitoCustomerUserpoolIDP);
}
Following an upgrade from Symfony 4.4.41 to 4.4.42 I seem to be unable to use 'target' in the following way:
/**
* Attempting to login as the specified user.
*
* #Route(
* "/login",
* name = "crmpicco_login"
* )
* #Template("#App/Register/login.html.twig")
*
* #param Request $request
* #param LoginHelper $loginHelper
*
* #return array
*/
public function loginAction(Request $request, LoginHelper $loginHelper): array
{
return $this->loginHelper($request, $loginHelper);
}
/**
* #param Request $request
* #param LoginHelper $loginHelper
*
* #return array
*/
protected function loginHelper(Request $request, LoginHelper $loginHelper): array
{
/* #var $session \Symfony\Component\HttpFoundation\Session\Session */
$session = $request->getSession();
// get the error if any (works with forward and redirect -- see below)
if ($request->attributes->has(LoginSecurity::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(LoginSecurity::AUTHENTICATION_ERROR);
} elseif (null !== $session && $session->has(LoginSecurity::AUTHENTICATION_ERROR)) {
$error = $session->get(LoginSecurity::AUTHENTICATION_ERROR);
$session->remove(LoginSecurity::AUTHENTICATION_ERROR);
} else {
$error = '';
}
$csrfToken = $this->getContainerInterface()->get('security.csrf.token_manager')->getToken('authenticate');
return [
'error' => $error,
'csrf_token' => $csrfToken,
'target' => 'crmpicco_register_details',
];
}
I can see there were some changes to the DefaultAuthenticationSuccessHandler in 4.4.42, however it's unclear how to fix this in my application.
My SuccessHandler looks like this:
public function onAuthenticationSuccess(Request $request, TokenInterface $token): RedirectResponse
{
return $this->httpUtils->createRedirectResponse($request, $this->determineTargetUrl($request));
}
What I am experiencing is the redirect is not respecting the "crmpicco_register_details" route I am passing through and is instead redirecting to the default "admin" route on successful login.
How do I remedy this in my application? (For now, i've reverted to 4.4.41 until I can fix this).
I created a discussion on Github (#46677) for this, but someone pointed out to me that it's more of an issue than a discussion.
I have a scenario like this:
The system handles reservations from couple of different sources. All bookings come in the form of a json with differing formats for each source. Some JSON attributes are present in one JSON and not in the other etc.
In order to enter the reservation into the system, I am trying to centralize the Add Reservation logic into one method. To do this, I am trying to create a class called Reservation using the Builder pattern as such:
<?php
namespace App\Business\Classes\Reservation;
use App\Business\Classes\Utils\ReservationUtils;
/**
* Class Reservation
* Holds entire reservation details
* #package App\Business\Classes\Reservation
*/
class Reservation
{
protected $reference, $otaReference, $hotelCode, $customerId, $guestName, $couponId, $checkin, $checkout, $guests, $customerCountry,
$commissionRate, $paymentStatus, $commissionOta, $commissionDifference, $rooms = [], $cityTax, $vat, $serviceCharge, $geniusBooker = false,
$geniusAmount = 0, $taxes, $taxIncluded = false, $supplierAmount, $totalAmount, $specialRequest, $currency, $deviceType, $bookingSource,
$otaRefId, $status, $source, $remarks;
public function __construct()
{
// generates a reference
$this->reference = ReservationUtils::referenceGenerator();
}
/**
* #param mixed $otaReference
* #return Reservation
*/
public function setOtaReference($otaReference): Reservation
{
$this->otaReference = $otaReference;
return $this;
}
/**
* #param mixed $checkin
* #return Reservation
*/
public function setCheckin($checkin): Reservation
{
$this->checkin = $checkin;
return $this;
}
/**
* #param mixed $checkout
* #return Reservation
*/
public function setCheckout($checkout): Reservation
{
$this->checkout = $checkout;
return $this;
}
/**
* #param array $rooms
* #return Reservation
*/
public function setRooms(array $rooms): Reservation
{
$this->rooms = $rooms;
return $this;
}
// and so on....
}
And I would use it like this:
$data= json_decode($result->jsonData);
$reservation = (new Reservation())
->setOtaReference($data->otaReference)
->setCheckin($data->checkin)
->setCheckout($data->checkout); //...etc
This is probably not the textbook usage of the builder pattern in PHP or even Java but is there anything wrong with it?
Thanks
Trying to include a php file in a script and even though the page loads without showing or logging errors, the included file is not executed.
I have created a test file that looks like this:
<?php
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
echo "commission counted"
?>
opening this file in browser completes the expected function.
Trying to include this same code in my script does not complete the function.
original script works good:
/**
* Swap current users plan to a new one.
*
* #return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
*/
public function swapPlan() {
if ($this->user->subscribed() && Input::get('plan')) {
$this->user->subscription(Input::get('plan'))->swap();
return response(trans('app.planSwapSuccess', ['plan' => Input::get('plan')]), 200);
}
}
Including my file in this script does not have the expected effect.
/**
* Swap current users plan to a new one.
*
* #return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
*/
public function swapPlan() {
if ($this->user->subscribed() && Input::get('plan')) {
$this->user->subscription(Input::get('plan'))->swap();
return response(trans('app.planSwapSuccess', ['plan' => Input::get('plan')]), 200);
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
}
}
The page will complete loading without errors, however the function that should be completed by the included file is not executed. Any Ideas on what I may have done wrong are appreciated.
I have spent a few days trying to figure this out. Since my test file works I'm guessing I'm missing something obvious in the full script.
Thanks for looking.
Comeplete file:
<?php namespace App\Http\Controllers;
use App;
use Auth;
use Input;
use Stripe\Stripe;
use Stripe\Plan;
class PaymentsController extends Controller {
public function __construct() {
$this->middleware('loggedIn');
$this->middleware('paymentsEnabled');
$this->user = Auth::user();
$this->settings = App::make('App\Services\Settings');
Stripe::setApiKey($this->settings->get('stripe_secret_key'));
}
/**
* Subscribe user to a plan or swap him to a different plan.
*
* #return response
*/
public function upgrade() {
if ($this->user->subscribed()) {
$this->user->subscription(Input::get('plan'))->swap();
} else {
$this->user->subscription(Input::get('plan'))->create(Input::get('stripe_token'), ['email' => $this->user->email]);
}
return response(trans('app.upgradeSuccess'), 200);
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
}
/**
* Swap current users plan to a new one.
*
* #return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
*/
public function swapPlan() {
if ($this->user->subscribed() && Input::get('plan')) {
$this->user->subscription(Input::get('plan'))->swap();
return response(trans('app.planSwapSuccess', ['plan' => Input::get('plan')]), 200);
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
}
}
/**
* Attach new credit card to user.
*
* #return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
*/
public function addNewCard() {
$this->user->updateCard(Input::get('stripe_token'));
return response(trans('app.cardAddSuccess'), 200);
}
/**
* Resume a canceled subscription.
*/
public function resumeSubscription() {
$this->user->subscription(Input::get('plan'))->resume(Input::get('token'));
return $this->user;
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
}
/**
* Cancel users subscription.
*
* #return \App\User
*/
public function unsubscribe() {
$this->user->subscription()->cancel();
return $this->user;
}
/**
* Return current users invoices.
*
* #return array
*/
public function getInvoices() {
return view('invoices')->with('invoices', $this->user->invoices())->with('settings', $this->settings);
}
/**
* Download invoice with given id.
*
* #param {int|string} $id
* #return \Symfony\Component\HttpFoundation\Response
*/
public function downloadInvoice($id) {
return $this->user->downloadInvoice($id, [
'vendor' => $this->settings->get('invoiceVendor'),
'product' => $this->settings->get('invoiceProduct'),
]);
}
/**
* Return all created plans.
*
* #return array
*/
public function getPlans() {
$plans = Plan::all();
$formatted = [];
foreach($plans->data as $plan) {
$formatted[] = [
'interval' => $plan['interval'],
'name' => $plan['name'],
'amount' => $plan['amount'] / 100,
'currency' => $plan['currency'],
'id' => $plan['id'],
'created' => $plan['created'],
];
}
usort($formatted, function($a1, $a2) {
if ($a1['created'] == $a2['created']) return 0;
return ($a1['created'] < $a2['created']) ? -1 : 1;
});
return $formatted;
}
}
Your method ends on return, meaning your include in the methods and variables being set are never reached.
An example:
Moving said include and variables to before the return should solve the issue.
/**
* Resume a canceled subscription.
*/
public function resumeSubscription() {
$this->user->subscription(Input::get('plan'))->resume(Input::get('token'));
// Moved to before return
$sale_amount = '10.00';
$product = 'Drive-Plan';
include('partners/controller/record-sale.php');
return $this->user;
// UNREACHABLE
//$sale_amount = '10.00';
//$product = 'Drive-Plan';
//include('partners/controller/record-sale.php');
}
Routes - I have 2 routes related to this
Route::resource('items', 'ItemsController');
Route::get('process/{process}/items', 'ItemsController#index');
When I use the 2nd, the index function (in the controller mentioned above) picks up the process id and runs without a hitch.
This is the link on a separate view which uses the 2nd route listed above:
{{ HTML::link('process/'.$process->id.'/items', 'Manage Items', array('class' =>'btn btn-primary')) }}
When I use a redirect from the update function in the same controller I get
"Missing argument 1 for ItemsController::index()"
which is the function that accepts the parameter so it can display all the items with that id.
It doesn't seem to matter what I use. Here are some of the statements I've tried in order to redirect to the index function:
return Redirect::route('items.index', array($data['process_id']));
return Redirect::action('ItemsController#index', array($data['process_id']));
I've also tried using "with(...)"
The following (using either route or action) gives me a "route not defined" error:
return Redirect::action('process/'.$data['process_id'].'/items');
I don't think its good practice to recreate the view as in the index function. I should just be able to redirect and have done with it.
What am I doing wrong?
The model relatioships are as follows:
1 project hasmany items
1 item hasmany attributes
1 attribute hasmany extensions
controller source code
<?php
class ItemAttributesController extends \BaseController {
/**
* Display a listing of itemattributes
*
* #return Response
*/
public function index($item_id)
{
return $this->makeIndex($item_id);
}
/**
* Show the form for creating a new itemattribute
*
* #return Response
*/
public function create()
{
return View::make('item_attributes.create');
}
/**
* Store a newly created itemattribute in storage.
*
* #return Response
*/
public function store()
{
$validator = Validator::make($data = Input::all(), Itemattribute::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$attribute = Itemattribute::create($data);
// add created attribute id to sequence in the item for this attribute
$item = Item::findOrFail($attribute->item_id);
// get the sequence data
// append the attribute id
if (isset($item->attribute)){
$item->attribute = $item->attribute.', '.$attribute->id;
} else {
$item->attribute = $attribute->id;
}
$item->save();
return $this->makeIndex($data['item_id']);
}
/**
* Display the specified itemattribute.
*
* #param int $id
* #return Response
*/
public function show($id)
{
$itemattribute = Itemattribute::findOrFail($id);
return View::make('item_attributes.show', compact('itemattribute'));
}
/**
* Show the form for editing the specified itemattribute.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
$itemattribute = Itemattribute::find($id);
return View::make('item_attributes.edit', compact('itemattribute'));
}
/**
* Update the specified itemattribute in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
$itemattribute = Itemattribute::findOrFail($id);
$validator = Validator::make($data = Input::all(), Itemattribute::$rules);
if ($validator->fails())
{
return Redirect::back()->withErrors($validator)->withInput();
}
$itemattribute->update($data);
return $this->makeIndex($data['item_id']);
}
/**
* Remove the specified itemattribute from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
$attribute = Itemattribute::findOrFail($id);
//find the item
$item = Item::findOrFail($attribute->item_id);
// get the sequence string
if (isset($item->attribute)){
// convert to array
$arr=explode(",",$item->attribute);
// remove item
if(($key = array_search($id, $arr)) !== false) {
unset($arr[$key]);
}
// convert back to string and replace initial string
$item->attribute = implode(",", $arr);
// save
$item->save();
}
ItemAttribute::destroy($id);
// return Redirect::route('item_attributes.index');
return $this->makeIndex($attribute->item_id);
}
private function makeIndex($item_id){
$item = Item::findOrFail($item_id);
$project = Project::findOrFail($item->project_id);
$item_attributes = DB::table('item_attributes')->where('item_id', $item->id)->get();
return View::make('item_attributes.index', compact('item_attributes', 'item', 'project'));
// return Redirect::to('item_attributes', );
}
}
routes source code
Route::get('/', function()
{
return View::make('home');
});
Route::resource('projects', 'ProjectsController');
Route::resource('items', 'ItemsController');
Route::resource('item_attributes', 'ItemAttributesController');
Route::resource('attribute_extentions', 'AttributeExtensionsController');
Route::get('project/{projects}/items', 'ItemsController#index');
Route::get('project/{projects}/item/create', 'ItemsController#create');
Route::get('item/{items}/item_attributes', array('as' => 'item_attributes', 'uses' => 'ItemAttributesController#index'));
Route::get('item/{items}/attribute_extentions', 'AttributeExtensionsController#index');
You are not using the route action correctly, it should point to the controller#function.
return Redirect::action('ItemsController#index', array('item_id' => 1));
Fixed it!
The solution was to use
return Redirect::to('item/'.$item->id.'/item_attributes');
This correctly passed the parameter in way that it could be picked up as a parameter by the function.
Thanks for all your help!