I can't clone array collection object because it says it is not an object.
This is my action here:
public function editAction(Request $request, Post $post)
{
$deleteForm = $this->createDeleteForm($post);
$editForm = $this->createForm('AppBundle\Form\PostType', $post);
$editForm->handleRequest($request);
var_dump($post->getPostImages()); // object
// $original_images = clone $post->getPostImages(); says not object
$original_images = $post->getPostImages();
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$postImages = $post->getPostImages();
$post->setPostImages([]);
var_dump($original_images); // not same as 1st dump
die;
foreach ($postImages as $image) {
$fileName = md5(uniqid()).'.'.$image->guessExtension();
if ($image->move(
$this->container->getParameter('post_image').$post->getTitle(),
$fileName)) {
// $images[] = $fileName;
$post->addPostImage(array('fileName' => $fileName));
}
}
$em->persist($post);
$em->flush();
return $this->redirectToRoute('post_edit', array('id' => $post->getId()));
}
if ($this->checkAction($post)) {
return $this->checkAction($post);
}
return $this->render('post/edit.html.twig', array(
'post' => $post,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
The 1st var dump returns this:
object(Doctrine\Common\Collections\ArrayCollection)#380 (1) { ["elements":"Doctrine\Common\Collections\ArrayCollection":private]=> array(1) { [0]=> array(1) { ["fileName"]=> string(36) "ba2a3dd44902cc4411e6508015f026a3.png" } } }
When I try to clone the object I get this:
Error: __clone method called on non-object
And the 2nd var dump returns this (after submitting the form) :
array(1) {
[0]=>
object(Symfony\Component\HttpFoundation\File\UploadedFile)#14 (7) {
["test":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=>
bool(false)
["originalName":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=>
string(34) "Screenshot_2016-06-20_14-28-36.png"
["mimeType":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=>
string(9) "image/png"
["size":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=>
int(610945)
["error":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=>
int(0)
["pathName":"SplFileInfo":private]=>
string(14) "/tmp/phpoY3L5i"
["fileName":"SplFileInfo":private]=>
string(9) "phpoY3L5i"
}
}
Update #1:
The form builder:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\CallbackTransformer;
class PostType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('content')
->add('postImages', FileType::class, array('label' => 'Post Image', 'multiple' => true, 'data_class' => 'Doctrine\Common\Collections\ArrayCollection', 'required' => false))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Post'
));
}
}
Apparently moving:
$original_images = $post->getPostImages();
Above:
$editForm->handleRequest($request);
Did the trick, now the code looks like this:
$deleteForm = $this->createDeleteForm($post);
$editForm = $this->createForm('AppBundle\Form\PostType', $post);
$original_images = $post->getPostImages();
$editForm->handleRequest($request);
Related
I am trying to add google calendar for my laravel project. So I generate the API key and whatever required credentials in google console. Then trying to apply them into my project and the relevant file are attached bellow... When I run the project experiencing error like this...
My client_secret.json file is something like this...
My controller file like this.... Actually I don't have much idea over here but use the code which is extracted from google calendar API reference.
<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Google_Client;
use Google_Service_Calendar;
use Google_Service_Calendar_Event;
use Google_Service_Calendar_EventDateTime;
use Illuminate\Http\Request;
class gCalendarController extends Controller
{
protected $client;
public function __construct()
{
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Calendar::CALENDAR);
$guzzleClient = new \GuzzleHttp\Client(array('curl' => array(CURLOPT_SSL_VERIFYPEER => false)));
$client->setHttpClient($guzzleClient);
$this->client = $client;
}
public function index()
{
session_start();
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$this->client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($this->client);
$calendarId = 'primary';
$results = $service->events->listEvents($calendarId);
return $results->getItems();
} else {
return redirect()->route('oauthCallback');
}
}
public function oauth()
{
session_start();
$rurl = action('gCalendarController#oauth');
$this->client->setRedirectUri($rurl);
if (!isset($_GET['code'])) {
$auth_url = $this->client->createAuthUrl();
$filtered_url = filter_var($auth_url, FILTER_SANITIZE_URL);
return redirect($filtered_url);
} else {
$this->client->authenticate($_GET['code']);
$_SESSION['access_token'] = $this->client->getAccessToken();
return redirect()->route('cal.index');
}
}
public function create()
{
return view('calendar.createEvent');
}
public function store(Request $request)
{
session_start();
$startDateTime = $request->start_date;
$endDateTime = $request->end_date;
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$this->client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($this->client);
$calendarId = 'primary';
$event = new Google_Service_Calendar_Event([
'summary' => $request->title,
'description' => $request->description,
'start' => ['dateTime' => $startDateTime],
'end' => ['dateTime' => $endDateTime],
'reminders' => ['useDefault' => true],
]);
$results = $service->events->insert($calendarId, $event);
if (!$results) {
return response()->json(['status' => 'error', 'message' => 'Something went wrong']);
}
return response()->json(['status' => 'success', 'message' => 'Event Created']);
} else {
return redirect()->route('oauthCallback');
}
}
public function show($eventId)
{
session_start();
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$this->client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($this->client);
$event = $service->events->get('primary', $eventId);
if (!$event) {
return response()->json(['status' => 'error', 'message' => 'Something went wrong']);
}
return response()->json(['status' => 'success', 'data' => $event]);
} else {
return redirect()->route('oauthCallback');
}
}
public function update(Request $request, $eventId)
{
session_start();
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$this->client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($this->client);
$startDateTime = Carbon::parse($request->start_date)->toRfc3339String();
$eventDuration = 30; //minutes
if ($request->has('end_date')) {
$endDateTime = Carbon::parse($request->end_date)->toRfc3339String();
} else {
$endDateTime = Carbon::parse($request->start_date)->addMinutes($eventDuration)->toRfc3339String();
}
// retrieve the event from the API.
$event = $service->events->get('primary', $eventId);
$event->setSummary($request->title);
$event->setDescription($request->description);
//start time
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime($startDateTime);
$event->setStart($start);
//end time
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime($endDateTime);
$event->setEnd($end);
$updatedEvent = $service->events->update('primary', $event->getId(), $event);
if (!$updatedEvent) {
return response()->json(['status' => 'error', 'message' => 'Something went wrong']);
}
return response()->json(['status' => 'success', 'data' => $updatedEvent]);
} else {
return redirect()->route('oauthCallback');
}
}
public function destroy($eventId)
{
session_start();
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$this->client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($this->client);
$service->events->delete('primary', $eventId);
} else {
return redirect()->route('oauthCallback');
}
}
}
My services.php file is like this...
<?php
return [
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect_uri' => env('GOOGLE_REDIRECT_URI'),
'redirect_callback' => env('GOOGLE_REDIRECT_CALLBACK'),
'scopes' => [
\Google_Service_Calendar::CALENDAR_EVENTS_READONLY,
\Google_Service_Calendar::CALENDAR_READONLY,
\Google_Service_Oauth2::OPENID,
\Google_Service_Oauth2::USERINFO_EMAIL,
\Google_Service_Oauth2::USERINFO_PROFILE,
],
'approval_prompt' => env('GOOGLE_APPROVAL_PROMPT', 'force'),
'access_type' => env('GOOGLE_ACCESS_TYPE', 'offline'),
'include_granted_scopes' => true,
],
];
I'm facing a weird problem that only accurs when I use pagination with livewire components,
this is the error:
BadMethodCallException
Method Illuminate\Support\Collection::items does not exist.
I know what this errors means, the problem is why it only accurs when I change page in pagination:
this is my Component:
<?php
namespace App\Http\Livewire\Admin;
use Livewire\Component;
use Livewire\WithPagination;
use Livewire\WithFileUploads;
use App\Models\Product;
use App\Models\Category;
use File;
use GlobalsHelper;
class Products extends Component
{
use WithPagination, WithFileUploads;
public $products;
public $subcategories;
// Form
public $name;
public $description;
public $price;
public $quantity;
public $category_id = null;
public $sub_category_id = null;
public $image;
public $selected = [];
public $query = '';
public $filter_by_category = '';
protected $paginationTheme = 'bootstrap';
public function render()
{
$pagination = $this->products;
$this->products = collect($this->products->items());
return view('livewire.admin.products', [
'categories' => Category::all(),
'subcategories' => $this->subcategories,
'products' => $this->products,
'pagination' => $pagination
]);
}
// public function render()
// {
// return view('livewire.admin.products', [
// 'categories' => Category::all(),
// 'subcategories' => $this->subcategories,
// 'products' => $this->products,
// ]);
// }
public function mount()
{
$this->getSubcategories();
$this->index();
}
public function getSubcategories()
{
$this->subcategories = [];
if ( !$this->category_id )
{
$this->category_id = (Category::first()) ? Category::first()->id : null;
}
$category = Category::find($this->category_id);
if ( !$category )
{
return null;
}
$this->subcategories = $category->children;
$this->sub_category_id = ($this->subcategories->first()) ? $this->subcategories->first()->id : null;
}
public function store()
{
$fields = $this->validate([
'name' => ['required', 'string', 'min:5', 'max:250'],
'description' => ['string', 'max:250'],
'price' => ['required', 'numeric', 'min:1'],
'quantity' => ['required', 'numeric', 'min:1'],
'category_id' => ['nullable'],
'sub_category_id' => ['nullable'],
]);
$fields['user_id'] = GlobalsHelper::auth()->id;
$product = Product::create($fields);
if ( !$product )
{
session()->flash('error', __('messages.error_create'));
return;
}
// upload image
$this->storeImage($product);
$this->resetFields();
session()->flash('success', __('messages.success_create'));
}
public function search()
{
$results = Product::where('name', 'LIKE', '%'.$this->query.'%')
->orderBy('id', 'desc')->paginate(5);
$this->products = $results;
}
public function index()
{
$this->products = Product::orderBy('id', 'desc')->paginate(5);
}
public function filterByCategory()
{
$results = Product::where('category_id', '=', $this->filter_by_category)
->orderBy('id', 'desc')->paginate(5);
$this->products = $results;
}
// private
private function resetFields()
{
$this->name = null;
$this->description = null;
$this->price = 0;
$this->quantity = 1;
$this->image = null;
$this->filename = '...';
}
private function storeImage($product)
{
$this->validate([
'image' => ['nullable', 'image', 'max:1024'],
]);
if ( $this->image )
{
// Delete old image if exists
if ( $product->image )
{
File::delete([$product->image->fullpath]);
}
$filename = sha1( uniqid('', true) );
$ext = $this->image->getClientOriginalExtension();
$fullpath = $this->image->store(GlobalsHelper::PRODUCTS_UPLOADS_DIR.'/'.$product->id, 'public');
$product->update([
'image' => [
'name' => basename($fullpath),
'type' => $ext,
'fullpath' => GlobalsHelper::STORAGE_DIR.$fullpath,
'url' => asset(GlobalsHelper::STORAGE_DIR.$fullpath)
]
]);
}
}
}
The idea is that I want to achieve search, store, update, delete, filter operations in same compoenent like in laravel controller, I found solutions online, but only 50% of what I need to achieve.
I have been wasting a lot of time trying to figure this out.
If any one would help me, I will be much appreciated.
At first glance without seeing the view, you are getting the $produts via the mount() method, this will only run ONCE when the livewire component is first rendered. From the docs:
mount() is only ever called when the component is first mounted and will not be called again even when the component is refreshed or rerendered.
I need to retrieve the last "order" created on the mySql database and pass it to a mail in order to be able to print a receipt, but it does not matter what i try, in the mail view it's always undefined. any tips for a newbie?
this is the controller that and sends the mail
public function token(Request $request)
{
$gateway = new \Braintree\Gateway([
'environment' => 'sandbox',
'merchantId' => 'jgvy755pfvwdcjzx',
'publicKey' => 'qqpm93srfgwtx6dp',
'privateKey' => 'd13ce21a7642606db73b12bb1300d3fd'
]);
$clientToken = $gateway->clientToken()->generate();
if ($request->input('nonce') != null) {
$request->validate([
'name' => 'required',
'last_name' => 'required',
'phone' => 'required',
'address' => 'required',
'email' => 'email:rfc',
]);
//# Storo l'ordine
$name = $request->input('name');
$last_name = $request->input('last_name');
$address = $request->input('address');
$phone = $request->input('phone');
$email = $request->input('email');
$arr_id = $request->input('arr_id');
$arr_quant = $request->input('arr_quant');
$delivery_fee = $request->input('delivery_fee');
//# Recupero tutti i piatti dell'ordine per calcolarne il totale
$dishes = Dish::findMany($arr_id);
$arrayLength = count($arr_id);
$amount = 0;
for ($i = 0; $i < $arrayLength; $i++) {
$amount += $dishes[$i]->price * $arr_quant[$i];
}
$amount += $delivery_fee;
//#
$newOrder = new Order();
$newOrder->status = 1;
$newOrder->address = $address;
$newOrder->user_name = $name;
$newOrder->user_surname = $last_name;
$newOrder->phone = $phone;
$newOrder->email = $email;
$newOrder->total = $amount;
$newOrder->save();
// // storo l'array di IDs
// Ciclo una volta per ogni piatto contenuto nell'ordine, salvo la relazione e la sua quantitÃ
for ($i = 0; $i < $arrayLength; $i++) {
$dish_id = $arr_id[$i];
// Scrive nella tabella pivot dopo aver creato la relazione
$newOrder->dishes()->attach([$dish_id => ['quantity' => $arr_quant[$i]]]);
//
}
//#
var_dump($request->input('nonce'));
$nonceFromTheClient = $request->input('nonce');
$gateway->transaction()->sale([
'amount' => $amount,
'paymentMethodNonce' => $nonceFromTheClient,
'options' => [
'submitForSettlement' => True
]
]);
Mail::to($email)->send(new PaymentConfirmationMail());
return view('orders.success');
}
return view('orders.braintree', ['token' => $clientToken]);
}
public function success(Request $request)
{
return view('orders.success');
}
}
this is the mail
class PaymentConfirmationMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('mails.payment_confirmation_mail');
}
}
Your Mail class isn't being told anything about the new order - you need to pass it to it :
Mail::to($email)->send(new PaymentConfirmationMail($newOrder));
then in your Mail class you need to be prepared to receive it :
protected $newOrder;
public function __construct(Order $newOrder) {
$this->newOrder = $newOrder
}
And also then pass the newOrder to the view :
public function build() {
$newOrder = $this->newOrder;
return $this->view('mails.payment_confirmation_mail')->with(compact('newOrder);
}
It should then be usable in your view with {{ $newOrder->something }}.
I am using Laravel-8 and Maatwebsite-3.1 package to import Excel into the DB using Laravel API as the endpoint.
Trait:
trait ApiResponse {
public
function coreResponse($message, $data = null, $statusCode, $isSuccess = true) {
if (!$message) return response() - > json(['message' => 'Message is required'], 500);
// Send the response
if ($isSuccess) {
return response() - > json([
'message' => $message,
'error' => false,
'code' => $statusCode,
'results' => $data
], $statusCode);
} else {
return response() - > json([
'message' => $message,
'error' => true,
'code' => $statusCode,
], $statusCode);
}
}
public
function success($message, $data, $statusCode = 200) {
return $this - > coreResponse($message, $data, $statusCode);
}
public
function error($message, $statusCode = 500) {
return $this - > coreResponse($message, null, $statusCode, false);
}
}
Import:
class EmployeeImport extends DefaultValueBinder implements OnEachRow, WithStartRow, SkipsOnError, WithValidation, SkipsOnFailure
{
use Importable, SkipsErrors, SkipsFailures;
public function onRow(Row $row)
{
$rowIndex = $row->getIndex();
if($rowIndex >= 1000)
return; // Not more than 1000 rows at a time
$row = $row->toArray();
$employee = Employee::create([
'first_name' => $row[0],
'other_name' => $row[1] ?? '',
'last_name' => $row[2],
'email' => preg_replace('/\s+/', '', strtolower($row[3])),
'created_at' => date("Y-m-d H:i:s"),
'created_by' => Auth::user()->id,
]);
public function startRow(): int
{
return 2;
}
}
Controller:
public function importEmployee(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'document' => 'file|mimes:xls,xlsx|max:5000',
]);
if ($request->hasFile('document'))
{
if($validator->passes()) {
$import = new EmployeeImport;
$file = $request->file('document');
$file->move(public_path('storage/file_imports/employee_imports'), $file->getClientOriginalName());
Excel::import($import, public_path('storage/file_imports/employee_imports/' . $file->getClientOriginalName() ));
foreach ($import->failures() as $failure) {
$importerror = new ImportError();
$importerror->data_row = $failure->row(); // row that went wrong
$importerror->data_attribute = $failure->attribute(); // either heading key (if using heading row concern) or column index
$importerror->data_errors = $failure->errors()[0]; // Actual error messages from Laravel validator
$importerror->data_values = json_encode($failure->values());
$importerror->created_by = Auth::user()->id;
$importerror->created_at = date("Y-m-d H:i:s");
$importerror->save();
}
return $this->success('Employees Successfully Imported.', [
'file' => $file
]);
}else{
return $this->error($validator->errors(), 422);
}
}
} catch(\Throwable $e) {
Log::error($e);
return $this->error($e->getMessage(), $e->getCode());
}
}
I made it to SkipOnError and SkipOnFailure.
If there's error, it saves the error into the DB. This is working.
However, there is issue, if some rows fail it still display success (Employees Successfully Imported) based on this:
return $this->success('Employees Successfully Imported.
When there is partial upload, or all the rows or some of the rows have issues, I want to display this to the user. So that it will be interactive.
How do I achieve this?
Thanks
I added a custom column to invoice grid using an observer.
The problem is that I can't sort or filter by the new column.
I added a filter condition callback but the function is not called.
Here is my Observer.php
class DB_CustomGrid_Model_Adminhtml_Observer
{
public function onBlockHtmlBefore(Varien_Event_Observer $observer)
{
$block = $observer->getBlock();
$payment_methods = array();
$readConnection = Mage::getSingleton('core/resource')->getConnection('core_read');
$query = 'SELECT method FROM '.Mage::getSingleton('core/resource')->getTableName('sales/order_payment').' GROUP BY method';
$methods = $readConnection->fetchAll($query);
foreach($methods as $payment) {
if($payment["method"] !== 'free') {
$payment_methods[$payment["method"]] = Mage::getStoreConfig('payment/'.$payment["method"].'/title');
}
}
switch ($block->getType()) {
case 'adminhtml/sales_invoice_grid':
$block->addColumnAfter('state', array(
'header' => Mage::helper('sales')->__('Payment Method'),
'index' => 'method',
'type' => 'options',
'width' => '70px',
'options' => $payment_methods,
'filter' => false,
'filter_condition_callback' => array($this, '_myCustomFilter'),
), 'method');
break;
}
}
public function beforeCollectionLoad(Varien_Event_Observer $observer)
{
$collection = $observer->getOrderInvoiceGridCollection();
$collection->join(array('payment'=>'sales/order_payment'),'main_table.order_id=parent_id',array('method'));
}
protected function _myCustomFilter($collection, $column)
{
exit;
if (!$value = $column->getFilter()->getValue()) {
return $collection;
}
$collection->getCollection()->getSelect()->where("sales_order_payment.method like ?", "%$value%");
return $collection;
}
}
I added an exit; to check if the function is called or not.
Try this:
Add a new protected function to your observer class:
protected function _callProtectedMethod($object, $methodName) {
$reflection = new ReflectionClass($object);
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invoke($object);
}
Then call $block->sortColumnsByOrder() and the new function $this->_callProtectedMethod($block, '_prepareCollection') directly after $block->addColumnAfter();