How Can I Integrate Shippo API With Laravel 8 - laravel

I'm building an ecommerce website with Laravel 8, and I'm trying to incorporate real time shipping rates with Shippo API. I was able to install Shippo via composer, but I get an error saying too few arguements or undefined variable. I'm borrowing some code from article regarding Shippo, but I keep getting the errors. Are you having a similar problem? Did you solve it? Any help is appreciated. Here is my controller code,
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\ShipDivision;
use App\Models\ShipDistrict;
use App\Models\ShipState;
use App\Models\Product;
use App\Services\Shipping_New;
use App\Models\User;
use Auth;
use\App\Http\Controllers\Frontend\CartController;
use Gloudemans\Shoppingcart\Facades\Cart;
use Carbon\Carbon;
class CheckoutController extends Controller
{
/**
* #var Shipping
*/
private $shipping;
/**
* #var UserRepository
*/
private $user;
/**
* CheckoutController constructor.
* #param UserRepository $user
* #param Shipping $shipping
*/
public function __construct(User $user, Shipping_New $shipping)
{
$this->middleware('auth');
$this->shipping = $shipping;
$this->user = $user;
}
public function DistrictGetAjax($division_id) {
$ship = ShipDistrict::where('division_id',$division_id)->orderBy('district_name', 'ASC')->get();
return json_encode($ship);
}
public function StateGetAjax($district_id) {
$ship = ShipState::where('district_id',$district_id)->orderBy('state_name', 'ASC')->get();
return json_encode($ship);
}
public function CheckoutStore(Request $request) {
$data = array();
$data['name'] = $request->name;
$data['shipping_last_name'] = $request->shipping_last_name;
$data['email'] = $request->email;
$data['phone'] = $request->phone;
$data['zip'] = $request->zip;
$data['street1'] = $request->street1;
$data['company'] = $request->company;
$data['city'] = $request->city;
$data['country'] = $request->country;
$data['notes'] = $request->notes;
$data['state_id'] = $request->state_id;
$data['district_id'] = $request->district_id;
$data['division_id'] = $request->division_id;
$cartTotal = Cart::total();
// The rates is a complete object but for this we
// only need the rates_list items and will pass that.
if ($request->payment_method == 'stripe') {
return view('online-boutique-stores.payment.stripe', compact('data','cartTotal'));
}
elseif ($request->payment_method == 'paypal') {
$carts = Cart::content();
$cartQty = Cart::count();
$cartTotal = Cart::total();
return view('online-boutique-stores.payment.paypal', compact('data', 'cartTotal'));
}
else {
return 'cash';
}
}
}

Remove this your construct arguments. Because you don't see any use in these arguments. You can use this way ?
public function __construct()
{
$this->middleware('auth');
}

Related

How to send data to view on send email in Laravel

i try this but it show Undefinded data
public function forgotPassword(Request $req){
$token = rand();
$data = $token;
Mail::to($req->email)->send(new sendPass($data));
}
First up, that code is a little bit inefficient. Why write :
$token = rand();
$data = $token;
Mail::to($req->email)->send(new sendPass($data));
when you could just write :
Mail::to($req->email)->send(new sendPass(rand()));
The issue is almost certainly because you've not declared $data in your SendPass class as a private variable :
class SendPass extends Mailable {
use Queueable, SerializesModels;
private $data;
public function __construct(string $data)
{
$this->data = $data;
}
public function build()
{
$data = $this->$data;
... rest of your code goes here.
}

Adding key-value to Laravel result object/collection

New to Laravel. Have what seems like should be a non-issue, but is causing a headache.
I'm trying to insert a key-value pair (bookingRef) within the result object/collection returned, such that the result would be:
[{"class_id":7,"class_name":"beginner","class_slots_avail":100,"class_slots_booked":53,"class_date":"2020-12-07 21:47:23","class_time":"09:25:00","class_reg_price":350, bookingRef: 127}]
I've tried methods such as push, put and merge that will insert the key-value after the object returned, but this is not what I require.
Here is my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Booking;
use App\Http\Controllers\Auth;
use Illuminate\Support\Facades\Mail;
use DB;
class BookingsController extends Controller
{
//
function store(Request $request) {
$id = $request->input('class');
if(DB::table('classes')->where('class_id', '=', $id)->exists()) {
if(DB::table('classes')->where('class_id', '=', $id)->value('class_slots_booked')
< DB::table('classes')->where('class_id', '=', $id)->value('class_slots_avail')) {
$booking = new Booking();
$booking->class_id = $id;
$booking->user_id = \Auth::id();
$booking->save();
DB::table('classes')->where('class_id', '=', $id)->increment('class_slots_booked', 1);
if($booking) {
$confBook = DB::table('classes')->where('class_id', '=', $id)->get();
$confBook->bookingRef = $booking->id;
\error_log($confBook);
}
}
else return('CLASS FULLY BOOOOKED');
}
else return('CLASS NOT Available');
}
}
You can cut down on your queries and put this extra data in place with some adjustments:
function store(Request $request)
{
$id = $rquest->input('class');
$class = DB::table('classes')->where('class_id', $id)->first();
if ($class) {
if ($class->class_slots_booked < $class->class_slots_avail) {
$booking = new Booking();
$booking->class_id = $id;
$booking->user_id = $request->auth()->id;
if ($booking->save()) {
// adding the extra data
$class->bookingRef = $booking->id;
DB::table('classes')->where('class_id', $id)
->increment('class_slots_booked', 1);
$class->class_slots_booked++;
return view('view-booking', [
'bookings' => collect($class),
]);
}
// booking did not save
}
// unavailable
}
// class not found
}
This would be a little more convenient with a Model for the classes table and a relationship setup to Booking would be a plus as well.
I managed to resolve it, thanks to Lagbox's suggestion of using a model:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Booking;
use App\Models\Classes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
class BookingsController extends Controller
{
//
function store(Request $request) {
$id = $request->input('class');
$class = Classes::where('class_id', $id)->first();
if($class) {
if($class->class_slots_booked < $class->class_slots_avail) {
$booking = new Booking();
$booking->class_id = $id;
$booking->user_id = Auth::id();
if($booking->save()){
$class->where('class_id', $id)->increment('class_slots_booked');
$class->bookingRef = $booking->id;
return view('view-booking', ['bookings' => $class]);
}
}
else return('Class Fully Booked');
}
else return('Class Not Available');
}
};
From what I can see, the get() method returns an array with object(s), which is why object->new_property = value would not work. The first() method, however, seems to return a single object, which is why it would.
Seems I've got some reading up on models and collections to do.

Magento 2: How to get quote product id in an observer?

Product id is not displaying and through this error **{"0": "Warning: Invalid argument supplied for foreach() ** please help me to come out of this.
Here I want to return if the attribute code is not equal to 5431.
So how it is possible.
<?php
namespace Softadroit\Prescription\Observer;
use Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Event\Observer as EventObserver;
use Psr\Log\LoggerInterface;
class Orderplaceafter implements ObserverInterface
{
protected $_responseFactory;
protected $_url;
public function __construct(
\Magento\Framework\App\ResponseFactory $responseFactory,
\Magento\Framework\UrlInterface $url
) {
$this->_responseFactory = $responseFactory;
$this->_url = $url;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$event = $observer->getEvent();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$_checkoutSession = $objectManager->create('\Magento\Checkout\Model\Session');
$_quoteFactory = $objectManager->create('\Magento\Quote\Model\QuoteFactory');
//$quote = $block->getQuoteData();
/* $quote= $observer->getEvent()->getQuote();
$item = $quote->getAllVisibleItems();
foreach($item as $_item){
echo $_item->getProduct()->getId(); */
$event = $observer->getEvent();
//$item = $event->getQuoteItem();
foreach($event->getQuoteItem() as $_item){
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($_item->getProductId());
$is_priscription = $product->getData('prescription');
if($is_priscription != '5431'){
return;
}
}
if ($quote->getId()) {
$quote->setIsActive(1)->setReservedOrderId(null)->save();
$_checkoutSession->replaceQuote($quote);
$url = $this->_url->getUrl('prescription/index'); //('[ModuleName]/[ModuleName]/[[Action]');
$this->_responseFactory->create()->setRedirect($url)->sendResponse();
die();
}
}
}
Any help is really appreciated
Thanks in Advance!
Next Step
This is my updated code I get Product id here, Now I want if product attribute option id is not equal to 5431 then redirect to success page i.e (order-success) and if oroduct option id is equal to 5431 then redirect to the url defined below (prescription/index)
<?php
namespace Softadroit\Prescription\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Controller\ResultFactory;
use \Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\App\ObjectManager;
use Psr\Log\LoggerInterface;
class Orderplaceafter implements ObserverInterface
{
protected $_responseFactory;
protected $_url;
protected $_order;
public function __construct(
\Magento\Framework\App\ResponseFactory $responseFactory,
\Magento\Framework\UrlInterface $url,
\Magento\Sales\Api\Data\OrderInterface $order
) {
$this->_responseFactory = $responseFactory;
$this->_url = $url;
$this->_order = $order;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$event = $observer->getEvent();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$_checkoutSession = $objectManager->create('\Magento\Checkout\Model\Session');
$_quoteFactory = $objectManager->create('\Magento\Quote\Model\QuoteFactory');
$orderid = $observer->getEvent()->getOrderIds();
$order = $this->_order->load($orderid);
foreach($order->getItemsCollection() as $_item){
$product = $_item->getProductId();
//echo $_item->getName(); die();
$is_priscription = $_item->getProduct()->getMyCustomAttribute('prescription');
if($is_priscription != '5431'){
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$resultRedirect->setPath('order-success');
return $resultRedirect;
}
}
$order = $_checkoutSession->getLastRealOrder();
$quote = $_quoteFactory->create()->loadByIdWithoutStore($order->getQuoteId());
if ($quote->getId()) {
$quote->setIsActive(1)->setReservedOrderId(null)->save();
$_checkoutSession->replaceQuote($quote);
$url = $this->_url->getUrl('prescription/index'); //('[ModuleName]/[ModuleName]/[[Action]');
$this->_responseFactory->create()->setRedirect($url)->sendResponse();
die();
}
}
}
If you are observing the event checkout_onepage_controller_success_action you don't have direct access to the quote. Only to the order. And you cannot get it from the Checkout session instance either because the quote is removed from the session before the event is dispatched.
But you can get the quote through the order.
you will need firts to add the quote repository as a dependency to your observer
private $quoteRepository;
public function __construct(
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
....
) {
$this->quoteRepository = $quoteRepository;
....
}
Then, in the execute method you can do this
$order = $observer->getOrder();
$quoteId = $order->getQuoteId();
$quote = $this->qupteRepository->get($quoteId);
if ($quote && $quote->getId()) {
$items = $quote->getAllItems();
//loop through items ....
}
This will get you what you are trying to do.
But I think a better idea would be to not use the quote and the products to get what you need.
You should save the product attribute value on the quote when it is added to the cart and then transfet this to the order item created from the quote item.
This way, in your observer you can do $order = $observer->getOrder() and then loop through the order items $order->getAllItems() and check what you need.
PLease try this below:
<?php
namespace Softadroit\Prescription\Observer;
use Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Event\Observer as EventObserver;
use Psr\Log\LoggerInterface;
class Orderplaceafter implements ObserverInterface
{
protected $_responseFactory;
protected $_url;
public function __construct(
\Magento\Framework\App\ResponseFactory $responseFactory,
\Magento\Framework\UrlInterface $url,
\Magento\Quote\Model\QuoteRepository $quoteRepository,
\Magento\Sales\Model\OrderFactory $orderFactory,
\Magento\Checkout\Model\Session $checkoutSession
) {
$this->_responseFactory = $responseFactory;
$this->_url = $url;
$this->quoteRepository = $quoteRepository;
$this->orderFactory = $orderFactory;
$this->checkoutSession = $checkoutSession;
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
$event = $observer->getEvent();
$orderIds = $observer->getEvent()->getOrderIds();
$order = $this->orderFactory->create()->load($orderIds[0]);
$quote = $this->quoteRepository->get($order->getQuoteId());
$item = $quote->getAllItems();
foreach($item as $_item){
$product = $_item->getProduct();
$is_priscription = $product->getData('prescription');
if($is_priscription != "" && $is_priscription == '5431'){
return;
}
}
if ($quote->getId()) {
$quote->setIsActive(1)->setReservedOrderId(null)->save();
$this->checkoutSession->replaceQuote($quote);
$url = $this->_url->getUrl('prescription/index');
$this->_responseFactory->create()->setRedirect($url)->sendResponse();
die();
}
}
}
After that please run php bin/magento setup:upgrade

Laravel trait function not found

I have look all over stackoverflow and google and I cannot seem to solve my trait function not found. I have tried composer dump-autoload, my composer.json have the app directory connected and even checked my namespace and trait names. Here is my user controller.
<?php
namespace App\Http\Controllers;
use App\User;
use App\Traits\ControllerTrait;
use App\Http\Requests\UpdateUser;
use Illuminate\Http\Request;
use App\Http\Requests\IndexUser;
class UserController extends Controller
{
use ControllerTrait;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show multiple users.
*
* #return \Illuminate\Http\Response
*/
public function index(IndexUser $request)
{
$per_page = 50;
$order_by = 'id';
$sort_by = 'ASC';
if($request->has('per_page')) {
$per_page = $request->input('per_page');
}
if($request->has('order_by')) {
$order_by = $request->input('order_by');
}
if($request->has('sort_by')) {
$sort_by = $request->input('sort_by');
}
$users = User::when($request->has('select'), function ($query) use ($request) {
selectPrepare($query, $request->input('select'));
})->when($request->has('include'), function ($query) use ($request) {
if(!empty($request->input('include'))) {
$includedTables = explode(',', $request->input('include'));
$tables = array_map('trim', $includedTables);
return $query->with($tables);
}
return $query;
})->orderBy("{$order_by}", "{$sort_by}")
->paginate($per_page);
return response()->json($users);
}
}
}
Here is my Trait
<?php
namespace App\Traits;
trait ControllerTrait
{
/**
* Function: scopeSelectPrepare
public function selectPrepare($query, $select) {
if(!empty($select)) {
$selectedColumns = explode(',', $select);
$columns = array_map('trim', $selectedColumns);
return $query->select($columns);
}
return $query;
}
}
As you can see my name space for the Trait is App\Traits and call the use App\Traits\ControllerTrait in my controller then can the use ControllerTrait to get the functions from the trait. When I try to get the function to use in my query it says: Call to undefined function App\Http\Controllers\selectPrepare()
Is there something I am missing? I am new to the traits functionality of laravel but I thought I was following all of the examples and naming conventions. Can anyone see what I am doing wrong.
You need to use $this when accessing trait methods, just like you would for any other method:
$users = User::when($request->has('select'), function ($query) use ($request) {
$this->selectPrepare($query, $request->input('select'));

Comment/Post system in Laravel

I can't seem to get relationships concrete in my head with Laravel. Having tried to follow the docs for eloquent orm, I still can't get my foreign keys to mean something (I update them manually). Right now I am trying to get a bulletin board system to work. A user can create a bulletin post, and here it is working in my controller:
public function editPost($id)
{
$user = User::find($id);
$user->bulletin = new Bulletin;//new post
$user->bulletin->creator_id = $id;//why doesn't it automatically update given the relationship?
$user->bulletin->type = Input::get('type');
$user->bulletin->title = Input::get('title');
$user->bulletin->content = Input::get('bulletinEdit');
$user->bulletin->save();
if(Input::hasFile('bulletinImage')){
$extension = Input::file('bulletinImage')->getClientOriginalExtension();
$fileName = str_random(9).'.'.$extension;
$user->bulletin->photo = new Photo;
$user->bulletin->photo->user_id = $id;
$user->bulletin->photo->type = Input::get('type');
$user->bulletin->photo->filename = $fileName;
$user->bulletin->photo->touch();
$user->bulletin->photo->save();
Input::file('bulletinImage')->move('public/images/bulletin/',$fileName);
}
return Redirect::to('bulletin');
}
If I have the relationship set up properly, shouldn't the creator_id be updated automatically? Here is what I have in my models:
Bulletin
<?php
class Bulletin extends Eloquent {
public function creator()
{
return $this->belongsTo('User');
}
public function comments()
{
return $this->hasMany('Comment');
}
public function type()
{
//if 1 then, etc
}
public function photos(){
return $this->hasMany('Photo');
}
}
User
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function tags()
{
//TO REMOVE RECORD
//User::find(1)->tags()->detach();
return $this->belongsToMany('Tag');
}
public function createUser()
{
$password = Hash::make('secret');
}
public function bulletin()
{
return $this->hasMany('Bulletin','creator_id');
}
public function profile()
{
return $this->hasOne('Profile');
}
}
Could anybody give me some tips on tightening this up?
The way you are doing it should work, you are just using more code and Eloquent has some methods to help you attach relationships, so I would try something like this:
public function editPost($id)
{
$user = User::find($id);
// Create a new bulletin, passing the necesssary data
$bulletin = new Bulletin(Input::only(['type', 'title', 'bulletinEdit']));
// Attach the bulletin model to your user, Laravel should set the creator_id itself
$bulletin = $user->bulletin()->save($bulletin);
...
return Redirect::to('bulletin');
}
In your model, you'll have to:
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = ['type', 'title', 'bulletinEdit'];
...
}
So Laravel doesn't give you a MassAssignmentException.

Resources