send mail laravel stmp - php

I get this message when i try to send mail with laravel:
Maximum execution time of 60 seconds exceeded in
E:\xampp\htdocs\eCommerce\vendor\symfony\mailer\Transport\Smtp\Stream\SocketStream.php
on line 154
mail file
class VerifyEmail extends Mailable
{
use Queueable, SerializesModels;
public function __construct()
{
}
public function envelope()
{
return new Envelope(
subject: 'VerifyEmail',
);
}
public function content()
{
return new Content(
view: 'Control.auth.Verify',
);
}
public function attachments()
{
return [];
}
}

Related

how to create a unique key for caching query in laravel

I used repository in a project that caching all queries.
there's a BaseRepository.
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class BaseRepository implements BaseRepositoryInterface{
protected $model;
protected int $cacheDuration = 600; //per seconds
public function __construct(Model $model)
{
return $this->model = $model;
}
public function paginate(int $paginate,string $cacheKey)
{
return Cache::remember($cacheKey,$this->cacheDuration , function () use ($paginate) {
return $this->model->latest()->paginate($paginate);
});
}
// other methods ...
}
then i used this repository in my service
PostService:
use Illuminate\Support\Facades\App;
class PostService{
public PostRepositoryInterface $postRepository;
public function __construct()
{
$this->postRepository = App::make(PostRepositoryInterface::class);
}
public function paginate(int $paginate, string $cacheKey)
{
return $this->postRepository->paginate($paginate,$cacheKey);
}
}
finally i using the PostService in my controller
PostController:
class PostController extends Controller{
public PostService $postService;
public function __construct()
{
$this->postService = App::make(PostService::class);
}
public function index()
{
string $cacheKey = "posts.paginate";
return $this->postService->paginate(10);
}
}
the index method will return top 10 latest record correctly. now i need to create a unique CacheKey for all Repository queries. for example
TableName concat FunctionName // posts.paginate
so i can use this code into all method of Repository
public function paginate(int $paginate)
{
$cacheKey = $this->model->getTable().__FUNCTION__;
return Cache::remember($cacheKey,$this->cacheDuration , function () use ($paginate) {
return $this->model->latest()->paginate($paginate);
});
}
this is fine. but the problem is that this code repeat in all the method of this class.
if i use this code in another class, method name's will be incorrect.
What do you suggest to prevent duplication of this code?
I solve this problem by passing function name to another class
I created CacheKey class:
class CacheKey{
public static function generate(Model $model, $functionName):string
{
return $model->getTable()."_".$functionName;
}
}
Then in any method of repository we can use this helper class as follows:
$cacheKey = CacheKey::generate($this->model,__FUNCTION__);
you can easily use magic method in this way:
class CacheService {
private const $cacheableMethods = ['paginate'];
private $otherSerivce;
public __construct($otherSerivce) {
$this->otherSerivce = $otherSerivce;
}
public __get($method, $args) {
if(!in_array($method, static::$cachableMethods)) {
return $this->otherSerivce->{$method}(...$args);
}
return Cache::remember(implode([$method, ...$args], ':'), function () {
return $this->otherSerivce->{$method}(...$args);
});
}
}

Laravel Excel passing argument

I'm trying to pass argument to filter the data I want to export to Excel.
This is my code :
class UnitExport implements FromCollection
{
public function collection($proj_id)
{
return Unit::where('project_id', $proj_id);
}
}
class UnitController extends Controller
{
public function index($proj_id)
{
return view('dev-admin.projects.units.index', ['proj_id' => $proj_id]);
}
public function unitExcelExport($proj_id)
{
return Excel::download(new UnitExport($proj_id), 'Unit.xlsx');
}
}
When try this it says i receive an error says:
Declaration of
App\Http\Controllers\Developer\Admin\UnitExport::collection($proj_id)
must be compatible with
Maatwebsite\Excel\Concerns\FromCollection::collection()
You can't pass your argument directly to your collection function. Try this.
class UnitExport implements FromCollection
{
protected $proj_id;
public function __construct($proj_id)
{
$this->proj_id = $proj_id;
}
public function collection()
{
return Unit::where('project_id', $this->proj_id)->get();
}
}

Lumen Mailable Multiple Views (how to?)

I have the a controller that calls a Mail class that fetches a view to be sent to an email. I was able to successfully retrieve a single view. But how do I concat multiple views together?
My controller:
namespace App\Http\Controllers;
class TestController extends Controller
{
public function sendMail(){
$notification = new NotificationService();
$notification->sendMail();
}
}
Service:
namespace App\Services;
use App\Mail\Test;
use Illuminate\Support\Facades\Mail;
class NotificationService
{
public function sendMail(){
Mail::to(['test#email.com'])->send(new Test);
}
}
Mail:
namespace App\Mail;
use Illuminate\Mail\Mailable;
class Test extends Mailable
{
public function build()
{
$view = $this->getTestView();
return $view;
}
private function getTestView(){
return $this->view(['TestEmail']);
}
}
I need to be able to put together multiple views in the Mail Test Class:
EG:
namespace App\Mail;
use Illuminate\Mail\Mailable;
class Test extends Mailable
{
public function build()
{
$view = $this->getTestView();
$view2 = $this->getTestView2()
return $view . $view2;
}
private function getTestView(){
return $this->view(['TestEmail']);
}
// HOW DO I CALL THIS IN THE build()?
private function getTestView2(){
return $this->view(['TestEmail2']);
}
}
Just make a new view that includes both
FullEmail.blade.php
#include('TestEmail')
#include('TestEmail2')

Interface not binding to implementation

I'm building a Lumen app. I'm trying to use interface for my repositories. All my logic is wrapped in a composer package.
Here's my vendor/package/src/app/Providers/PackageServiceProvider.php:
<?php
namespace Vendor\Package\App\Providers;
use Illuminate\Support\ServiceProvider;
class SmsBackendCoreServiceProvider extends ServiceProvider
{
protected $defer = false;
public function register()
{
$this->app->bind(
'Vendor\Package\App\Repositories\Contracts\SmsService',
'Vendor\Package\App\Repositories\Services\SmsJson'
);
}
public function boot()
{
$this->app->group(
['namespace' => 'Vendor\Package\App\Http\Controllers'],
function ($app) {
require __DIR__.'/../../routes/web.php';
}
);
}
}
Here is my vendor/package/src/routes/web.php:
<?php
$app->get('/sms/send.json', 'JsonController#send');
Here is my vendor/package/src/app/Http/Controllers/JsonController.php:
<?php
namespace Vendor\Package\App\Http\Controllers;
use Vendor\Package\App\Http\Controllers\BaseController;
use Vendor\Package\App\Repositories\Contracts\SmsService;
class JsonController extends BaseController
{
public $service;
public function __construct(SmsService $service)
{
$this->service = $service;
}
public function send()
{
$response = $this->service->sendSms(1, 2, 3);
return $response;
}
}
Here is my vendor/package/src/app/Repositories/Contracts/SmsService.php:
<?php
namespace Vendor\Package\App\Repositories\Contracts;
class SmsService
{
public function sendSMS($from, $to, $text);
}
Finally, here is my vendor/package/src/app/Repositories/Services/SmsJson.php:
<?php
namespace Vendor\Package\App\Repositories\Services;
use Vendor\Package\App\Repositories\Contracts\SmsService;
class SmsJson implements SmsService
{
public function sendSMS($from, $to, $text)
{
echo 'success';
}
}
When I try to access http://mydomain.dev/sms/send.json, I get this error:
FatalErrorException in SmsService.php line 7: Non-abstract method
Mitto\SmsBackendCore\App\Repositories\Contracts\SmsService::sendSMS()
must contain body
Where did I go wrong?
Your contract is declared as a class, it must be an interface.

Mockery not calling method from repository (interface)

I am trying to test my controller with this test (I'm using Laravel, if that matters):
<?php
use Zizaco\FactoryMuff\Facade\FactoryMuff;
class ProjectControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->mock = $this->mock('Dumminvoicing\Storage\Project\ProjectRepositoryInterface');
}
public function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
protected function tearDown()
{
Mockery::close();
}
public function testRedirectWhenNotLogged()
{
Route::enableFilters();
$response = $this->call('GET', 'projects');
$this->assertRedirectedToAction('UserController#getLogin');
}
public function testAllowedWhenLogged()
{
Route::enableFilters();
//Create user and log in
$user = FactoryMuff::create('User');
$this->be($user);
$response = $this->call('GET', 'projects');
$this->assertResponseOk();
}
public function testIndex()
{
$this->mock->shouldReceive('all')->once();
$this->call('GET', 'projects');
$this->assertViewHas('projects');
}
}
Following these tutorials http://culttt.com/2013/07/08/creating-flexible-controllers-in-laravel-4-using-repositories/ http://culttt.com/2013/07/15/how-to-structure-testable-controllers-in-laravel-4/ I use repositories to avoid coupling my DB to the tests. So I have these 2 extra classes:
<?php
namespace Dumminvoicing\Storage\Project;
use Project;
class EloquentProjectRepository implements ProjectRepository
{
public function all()
{
return Project::all();
}
public function find($id)
{
return Project::find($id);
}
}
<?php
namespace Dumminvoicing\Storage\Project;
interface ProjectRepository
{
public function all();
public function find($id);
}
When I run the test, I get this error:
There was 1 error:
1) ProjectControllerTest::testIndex
Mockery\Exception\InvalidCountException: Method all() from Mockery_2143809533_Dumminvoicing_Storage_Project_ProjectRepositoryInterface should be called
exactly 1 times but called 0 times.
The index method of the controller works fine in the browser:
use Dumminvoicing\Storage\Project\ProjectRepository as Project;
class ProjectsController extends \BaseController
{
protected $project;
public function __construct(Project $project)
{
$this->project = $project;
$this->beforeFilter('auth');
}
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$data['projects'] = $this->project->all();
return View::make('projects.index', $data) ;
}
So why is it failing in the test? Why is "all" not being called?
If the user has to be authenticated to hit the index method, you need to authenticate each test.
The all isn't getting called because the user is being redirected.
Create an authentication method that you can call each time you need to authenticate the request.
To see why the test failing, dump out the response before you do the assert.
Edit
The problem is you've mocked Dumminvoicing\Storage\Project\ProjectRepositoryInterface but it should be Dumminvoicing\Storage\Project\ProjectRepository.
If you correct the namespace and add $this->mock->shouldReceive('all')->once(); to the testAllowedWhenLogged() method your tests will pass correctly.

Categories