PHP doc: state that you are returning the result of another function call - phpdoc

With a function like this:
function cancel($thing_id)
{
$this->Thing->id = $thing_id;
return $this->Thing->cancel();
}
How do I format the #return to reflect that I am returning the result of another function call?

It is not possible to link the return type to a different functions return type. It is not mentioned as a type in phpDocumentor: Defining a 'Type', and the closest thing would be the callable type.
The best thing you can do probably is the following:
/**
* As a example I have assumed that $this->Thing->cancel() returns either true or false
*
* #see Thing::cancel
* #return bool Returns the result of Thing::cancel
*/
As you can see, I specify the return type of $this->Thing->cancel() and explain where the return type originates from. To make it easy to find the method I added the #see tag, pointing to the method

Related

How to overwrite bulk clone function for laravel backpack

I am trying to overwrite a bulk clone function.
I just want to clone some values, and the rest assign a static value. For example, I just want to clone the name and description values, and the date I want to assign it the current date.
And well I don't know how to do it.
use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation { bulkClone as traitBulkClone; }
public function bulkClone($id) {
// your custom code here
$this->traitBulkClone($id);
}
TLDR: The most efficient way would probably be to overwrite the replicate() method on your model. Note that it is not a Backpack method, but an Eloquent method that BulkCloneOperation uses to duplicate a particular entry.
WHY?
Inside the BulkCloneOperation that you're using, you'll notice the route calls the bulkClone() method, that itself is just making some calls to the replicate() method on the model. That means you have two options to override this behaviour:
(Option A). Override the bulkClone() method in your CrudController. This will override the behaviour only on that particular admin operation.
(Option B). Override the replicate() method in you Model. That way, any time replicate() is called (by your admin panel or any other part of your software), the duplication is done in the way you specified.
In most cases, I think Option B is more appropriate, since it would avoid future code duplication. Here's Laravel's replicate() method at this time, just copy-pasting it into your model and modifying it to fit your needs is the best solution, if you ask me:
/**
* Clone the model into a new, non-existing instance.
*
* #param array|null $except
* #return static
*/
public function replicate(array $except = null)
{
$defaults = [
$this->getKeyName(),
$this->getCreatedAtColumn(),
$this->getUpdatedAtColumn(),
];
$attributes = Arr::except(
$this->getAttributes(), $except ? array_unique(array_merge($except, $defaults)) : $defaults
);
return tap(new static, function ($instance) use ($attributes) {
$instance->setRawAttributes($attributes);
$instance->setRelations($this->relations);
$instance->fireModelEvent('replicating', false);
});
}

Let undefined property be null value in Laravel

Is there any way to make object undefined property become null value?
Because laravel request object will auto make undefined property become null value like below.
$request->test; // This parameter never passed
error_log($request->test) //null
But when it comes to object or array it will throw errors.
$object->test // test is not defined
//Will throw ErrorException: Undefined property
What are the differences between them?
laravel request object uses magic method __get to actually to get the input element from the request. here is how it does things behind the scene.
/**
* Get an input element from the request.
*
* #param string $key
* #return mixed
*/
public function __get($key)
{
return Arr::get($this->all(), $key, function () use ($key) {
return $this->route($key);
});
}
you can use the __get magic method to avoid undefined property access exception as follows
/**
* check if attribute exists or not, if not exists return null.
*
* #param string $key
* #return mixed|null
*/
public function __get($key)
{
return isset($this->{$key})?$this->{$key}:null;
}
Use isset($your_object->its_propery). isset() will return false if got undefined else it return true.
The difference is that Request class has the magic method __get (check this) which will return null if the parameter that you are asking for doesn't exist on the request parameters.
So for example $request->test; won't be interpreted as "go and grab the test attribute of that object" but instead will run the __get($value) method, of that Class, which will check if that $value (that is in this case test) exists in the request parameters, if yes, the method will return that value, if not, will return null, where instead, if you don't create/have the magic method __get in your class, PHP will just check if that test is an attribute of your class, otherwise will return undefined.
You can always check if something is undefined using isset($value) function

How do you get the package name from a Composer event?

The Problem
I'm attempting to set up a post-update script with Composer that checks to see which package is being updated. However, I'm having trouble figuring out how to consistently get the package name from a Composer\Installer\PackageEvent.
Attempts to solve
The source code says that $packageEvent->getOperation->getReason() should return a string, but in my testing is actually returning an instance of Composer\DependencyResolver\GenericRule.
Calling Composer\DependencyResolver\Rule::getReasonData() sometimes returns a string (the package name), and sometimes returns Composer\Package\Link.
The following code mostly works to figure out the package's name:
$reasonData = $packageEvent->getOperation()->getReason()->getReasonData();
$packageName = is_string($reasonData) ? $reasonData : $reasonData->getTarget();
except sometimes $packageEvent->getOperation()->getReason() returns null.
The Question
How do you consistently get the package name from a Composer PackageEvent?
Bonus Points
How do you get the name of the package being installed/updated/etc. from all of the Composer event classes?
My mistake! Composer operations still have access to packages, just through different methods, which depend on whether the operation is an InstallOperation or an UpdateOperation. The following works:
/**
* Returns the package name associated with $event
*
* #param PackageEvent $event Package event
* #return string
*/
public static function getPackageName(PackageEvent $event)
{
/** #var InstallOperation|UpdateOperation $operation */
$operation = $event->getOperation();
$package = method_exists($operation, 'getPackage')
? $operation->getPackage()
: $operation->getInitialPackage();
return $package->getName();
}

Assertions with conditions

I would like to know if it is possible to use asser annotation with conditions.
Using symfony2, in my entity class, on one property I would like to put :
* #Assert\NotBlank()
if another property has 7 as a value.
Is that possible ?
As I mentioned in the comment, you can utilize Callback Constraint
It could look like this:
class YourEntity
{
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context, $payload)
{
if(($this->firstAttr == 7) && empty($this->secondAttr)) {
$context->buildViolation('Second can\'t be empty when first is 7!')
->atPath('secondAttr')
->addViolation();
}
}
}
You can also make an external callback validator which may be even more suitable since it won't make any mess in you model code (entities).

Laravel - pass parameters through app->bind to model's constructor

Well, code describes it all. I've an Entity Service Provider, which pass an instance of Playlist Model, which supposed to get an array as it's first constructor parameter. How to pass that parameter through app->bind? Knowing that EntityServiceProvider is automagically injected when referenced in the controller.
// Current Code
/**
* Playlist Entity
*
* #return Playlist\PlaylistEntity
*/
$this->app->bind('Playlist\PlaylistEntity', function($app)
{
return new PlaylistEntity($app->make('Playlist\PlaylistRepositoryInterface'));
});
// Should be something like this:
/**
* Playlist Entity
*
* #return Playlist\PlaylistEntity
*/
$this->app->bind('Playlist\PlaylistEntity', function($app)
{
return new PlaylistEntity($app->make('Playlist\PlaylistRepositoryInterface', $parameters));
});
Similar case: Laravel 4: Passing data from make to the service provider
Alex Russell's comment works for me as well.
The answer in the 'similar case' post is correct as far as I can tell. $this->app->bind('Whatever', function ($app, $params) { var_dump($params); }); followed by App::make('Whatever', [1, 2, 3]); var_dumps the [1, 2, 3] array for me.
In Laravel 5.4 the ability to pass config parameters when resolving from the container using App::make() was removed and subsequently re-implemented as App::makeWith().
BTW I tried to make this a comment on the previous answer, but it didn't let me. Maybe due to not enough experience points?
Thanks #yevgeniy-afanasyev for pointing out the problems when mocking. If you need to mock these instances, you could go for Taylor Otwell's early suggestion here: https://github.com/laravel/ideas/issues/391#issuecomment-285197048
I just needed that and it worked well. Just return a closure and call it, when you ::make.
// Service Provider
$this->app->bind(MyClass::class, function ($app) {
return function($param) : MyClass
{
return new MyClass($param);
}
}
// ::make
$myInstance = App::make(MyClass::class)($myParameter);
// mock
$myMock = Mockery::mock(new MyClass($myParameter));
$this->instance(MyClass::class, function($param) use ($myMock) { return $myMock; });

Resources