I have this scenario:
Interface ClassInterface
{
public function getContext();
}
Class A implements ClassInterface
{
public function getContext()
{
return 'CONTEXTA';
}
//Called in controller class
public function Amethod1()
{
try {
//assuming that Helper is a property of this class
$this->helper->helperMethod($this);
} catch(Exception $ex) {
throw $ex;
}
}
}
Class B implements ClassInterface
{
public function getContext()
{
return 'CONTEXTB';
}
//Called in controller class
public function Bmethod1()
{
try {
//assuming that Helper is a property of this class
$this->helper->helperMethod($this);
} catch(Exception $ex) {
throw $ex;
}
}
}
Class Helper {
public function helperMethod(ClassInterface $interface)
{
try {
$this->verifyContext($interface->getContext());
//dosomething
} catch(\Exception $ex) {
throw $ex;
}
}
private function verifyContext($context) {
if (condition1) {
throw new \UnexpectedValueException('Invalid context.');
}
return true;
}
}
I want my controller class which calls Amethod1 and Bmethod1 to know the type of exception(s) thrown in the process. Is it advisable to rethrow an exception just like it was presented?
Do you think the throw-catch-throw-catch-throw structure reasonable in this case?
Yes, totally reasonable. But: your specific example can be simplified from:
public function Amethod1()
{
try {
//assuming that Helper is a property of this class
$this->helper->helperMethod($this);
} catch(Exception $ex) {
throw $ex;
}
}
To:
public function Amethod1()
{
//assuming that Helper is a property of this class
$this->helper->helperMethod($this);
}
Related
I want to call function payrollProcess from another class inside my controller.
here's my code :
public function save(Request $request, $obj = null)
{
PayrollHelper::payrollProcess($PayrollPeriod);
return view('payroll_process.form');
}
and this is payrollHelper class code :
<?php
namespace App\Helpers;
use App\Helpers\Exceptions\ValidationException;
use App\Models\Config;
use App\Models\Driver;
use App\Models\DriverPayable;
use App\Models\PayrollPeriod;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Log;
final class PayrollHelper {
public static function processPayroll(PayrollPeriod $payrollPeriod)
{
try {
$drivers = Driver::where('active', true)->get();
foreach ($drivers as $driver) {
$payable = $payrollPeriod->driverPayables()
->where('driver_id', $driver->id)->first();
if (!$payable) {
$payable = new DriverPayable;
}
$payable->payrollPeriod()->associate($payrollPeriod);
$payable->driver()->associate($driver);
if (!$payable->save()) {
\Log::info($payable->errors());
throw new ValidationException($payable->errors());
}
}
} catch (Exception $e) {
Log::error($e);
SessionHelper::setMessage(
'Unable to process payroll, Please contact system Administrator'
);
} catch (ValidationException $e) {
Log::info($e->errors);
SessionHelper::setMessage($e->errors);
}
}
}
?>
I got this error when i run it. Call to undefined method App\Helpers\PayrollHelper::payrollProcess()
any idea ?
In PayrollHelper class you have defined processPayroll method so in your controller
public function save(Request $request, $obj = null)
{
PayrollHelper::payrollProcess($PayrollPeriod);
return view('payroll_process.form');
}
you are accessing undefined method
$module - is one of my classes, based on Interface and must be have public function getController. I can forget to add getController function in class, and after run i have this error:
ReflectionException in Container.php line 776:
Class App\Http\Controllers\ does not exist
and want to catch this exception, but this code not work:
try
{
\Route::get($module->getUrl(), $module->getController() . '#index');
}
catch (\ReflectionException $e)
{
echo 123123;
}
Code example:
namespace App\MyModules;
MyModuleManager::bindRoute();
interface MyModuleInterface
{
public function getUrl();
public function getController();
}
class MyClass implements MyModuleInterface
{
public function getUrl()
{
return '/url';
}
/*
* for example: this method i forgdet to add
* and in ModuleManager::bindRoute i want to cath exception
*
public function getController()
{
}
*/
}
class MyModuleManager
{
static public function bindRoute()
{
$module = new MyClass();
try
{
\Route::get($module->getUrl(), $module->getController() . '#index');
}
catch (\ReflectionException $e)
{
echo 123123;
}
}
}
In L5 you can handle this exception globally:
// Exceptions/Handler.php
use ReflectionException;
public function render($request, \Exception $e)
{
if ($e instanceof ReflectionException) {
// …
}
return parent::render($request, $e);
}
http://hacklang.org/tutorial/ - see last exercise (24).
...
trait T {
require extends C;
...
How would you achive this in PHP?
I'd like to use that in PHP Unit tests, like below:
class EventsTest extends TrafficWebTestCase
{
use EntityRepositoryMock;
use ValidatorMock;
use EventsDataProviderTrait;
An example of trait:
trait ValidatorMock
{
...
protected function getValidatorMock($validateObject, $return = [])
{
if (!method_exists($this, 'getMockForAbstractClass')) {
throw new InvalidTraitUseException();
}
$this->validatorMock = $this->getMockForAbstractClass(
'Symfony\Component\Validator\Validator\ValidatorInterface'
);
$this->validatorMock->expects($this->once())
->method('validate')
->with($this->equalTo($validateObject))
->willReturn($return);
return $this->validatorMock;
}
Those trait create some specific mocks or do other stuff that's only related to a unit test. In those traits I use methods from the \PHPUnit_Framework_TestCase, so I'd like to check if trait is used in a valid context.
I think you want something like that:
trait T
{
public function __construct()
{
if (!($this instanceof C)) {
die('Not an instance of C');
}
echo "Everything fine here<br />";
$this->someMethod();
}
}
class C
{
public function someMethod()
{
echo "required method<br />";
}
}
class A extends C
{
use T;
public function doSomething()
{
}
}
class B
{
use T;
public function doSomething()
{
}
}
$a = new A();
$b = new B();
Using instanceof you can check if object extends some class.
For the following code result will be:
Everything fine here
required method
Not an instance of C
More complex code (without checking in constructor):
trait T
{
public function myFunction()
{
$this->checkHierarchy();
echo "normal actions<br />";
}
public function secondFunction()
{
$this->checkHierarchy('D');
echo "normal actions<br />";
}
private function checkHierarchy($className = 'C')
{
if (!($this instanceof $className)) {
throw new \Exception('Not an instance of ' . $className . "<br />");
}
echo "Everything fine here<br />";
}
}
class C
{
public function someMethod()
{
echo "required method<br />";
}
}
class A extends C
{
use T;
public function doSomething()
{
}
public function __construct()
{
echo "aaa<br />";
}
}
class B
{
use T;
public function doSomething()
{
}
public function __construct()
{
echo "bbb<br />";
}
}
$a = new A();
try {
$a->myFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}
try {
$a->secondFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}
$b = new B();
try {
$b->myFunction();
} catch (\Exception $e) {
echo $e->getMessage();
}
I am getting unexpected T_TRY, expecting T_FUNCTION error message and am not sure as too why am getting that, can't we use try and catch block inside class like this:
class Processor
{
protected $dao;
protected $fin;
try
{
public function __construct($file)
{
//Open File for parsing.
$this->fin = fopen($file,'w+') or die('Cannot open file');
// Initialize the Repository DAO.
$this->dao = new Dao('some name');
}
public function initiateInserts()
{
while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
{
$initiate_inserts = $this->dao->initiateInserts($data);
}
}
public function initiateCUpdates()
{
while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
{
$initiate_updates = $this->dao->initiateCUpdates($data);
}
}
public function initiateExecuteIUpdates()
{
while (($data=fgetcsv($this->fin,5000,";"))!==FALSE)
{
$initiate_updates = $this->dao->initiateIUpdates($data);
}
}
}
catch (Exception $e)
{
}
}
You can't put all your method definitions into one try-catch block.
Instead of
class Foo {
try {
public function func1() { }
public function func2() { }
}
catch(Exception $e) {
}
}
you have to use
class Foo {
public function func1() {
try {
...
}
catch(Exception $e) {
...
}
}
public function func2() {
try {
...
}
catch(Exception $e) {
...
}
}
}
Don't try-catch inside of each method, you could simply try-catch when you use your class:
try {
$p = new Processor($file);
$p->initiateInserts();
$p->initiateCUpdates();
// and so on...
} catch (Exception $e) {
// handle the error...
}
This way your class will be much cleaner and you can decide what to do with errors. Especially if you use your class in multiple places - you can have customized error handling for each case.
You can't have any "do this stuff"-code in a class outside of a method. There is nothing to "try to do" inside those curly brackets, because the stuff inside is just method definitions.
I am learning OOP with PHP. I am creating a class to extract XML data from a website. My question is how do I stop the given object from executing more methods if there is an error with the first method. For example, I want to send the URL:
class GEOCACHE {
public $url;
public function __construct($url)
{
$this->url=$url;
if (empty($this->url))
{
echo "Missing URL";
}
}
public function secondJob()
{
whatever
}
}
when I write like this:
$map = new GEOCACHE ("");
$map->secondJob("name");
How do I prevent the secondJob method from being executed in that given object without the script terminating?
Throw an Exception in the constructor, therefore the object will never be created
public function __construct($url)
{
$this->url=$url;
if (empty($this->url))
{
throw new Exception("URL is Empty");
}
}
You can then do something like this:
try
{
$map = new GEOCACHE ("");
$map->secondJob("name");
}
catch ( Exception $e)
{
die($e->getMessage());
}
Consider using exceptions in order to control the flow of the script. Throw an exception in the constructor, and catch it outside.
class GEOCACHE {
public $url;
public function __construct($url)
{
$this->url=$url;
if (empty($this->url))
{
throw new Exception("Missing URL");
}
}
public function secondJob()
{
whatever
}
}
try{
$map = new GEOCACHE ("");
$map->secondJob("name");
}catch($e){
// handle error.
}
Throw an exception from __construct
public function __construct($url)
{
if(null == $url || $url == '')
{
throw new Exception('Your Message');
{
}
then in your code
try
{
$geocache = new Geocache($url);
$geocache->secondJob();
// other stuff
}
catch (exception $e)
{
// logic to perform if the geocode object fails
}