I want to collect the data taken from the event in my subscriber and then output them in collect function().
class MyDataCollector extends DataCollector implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
EventTypes::LOAD => 'providerLoad',
....
}
public static function create(EventDispatcherInterface $eventDispatcher)
{
$collector = new static();
$eventDispatcher->addSubscriber($collector);
return $collector;
}
}
Related
I've checked many repository design pattern tutorials like
https://asperbrothers.com/blog/implement-repository-pattern-in-laravel/
https://www.larashout.com/how-to-use-repository-pattern-in-laravel
https://laravelarticle.com/repository-design-pattern-in-laravel
https://shishirthedev.medium.com/repository-design-pattern-in-laravel-application-f474798f53ec
But all use multiple repositories with all methods repeated for each model here's an example
class PostRepository implements PostRepositoryInterface
{
public function get($post_id)
{
return Post::find($post_id);
}
public function all()
{
return Post::all();
}
}
interface PostRepositoryInterface
{
public function get($post_id);
public function all();
}
class PostController extends Controller
{
protected $post;
public function __construct(PostRepositoryInterface $post)
{
$this->post = $post;
}
public function index()
{
$data = [
'posts' => $this->post->all()
];
return $data;
}
}
In ReposiroryServiceProvider:
$this->app->bind(
'App\Repositories\PostRepositoryInterface',
'App\Repositories\PostRepository'
);
So now I have UserRepository, PostRepository, CommentRepository .... etc I will have to add the same methods of get, add, .... in all repositories and just change the model name from Post to User .... etc
How can I unify these methods in one file and just pass the model name and use it like this $this->model->all() instead of repeating them in every repository file I create?
You need Abstract Class AbstractRepository, something like this.
Btw, maybe you don't need repository pattern, in Laravel it is not best practice.
abstract class AbstractRepository
{
private $model = null;
//Model::class
abstract public function model(): string
protected function query()
{
if(!$this->model){
$this->model = app($this->model());
}
return $this->model->newQuery()
}
public function all()
{
return $this->query()->all();
}
}
Laravel: 6.x
PHP 7.3
I'am wirte a Repositorytest. below is my code, how can I fix this error,
error
TypeError: Return value of Mockery_5_App_Repositories_PersonRepository::fetchOrNewPersonById() must be an instance of App\Models\PersonModel, instance of Mockery\CompositeExpectation returned
Repository
class ContactRepository implements ContactRepositoryInterface
{
private $contact;
private $personRepo;
public function __construct(Contact $contact)
{
$this->contact= $contact;
$this->personRepo= app()->make(PersonRepositoryInterface::class);;
}
public function updateContacts(array $datas): bool
{
foreach ($datas as $key => $value) {
$person = $this->personRepo->fetchOrNewPersonById($value['person_id']);
$person->fill($value);
if( !$person->save()){ return false; }
}
return true;
}
}
and
class PersonRepository implements PersonRepositoryInterface
{
private $personModel;
public function __construct(Person $personModel)
{
$this->personModel= $personModel;
}
public function fetchOrNewPersonById($id): PersonModel
{
return $this->personModel->firstOrNew(['id' => $id]);
}
}
..which implements a Model.
class PersonModel extends Model
{
protected $table = 'person';
}
and
class Contact extends Model
{
protected $table = 'contacts';
}
my testing code
class ContactRepositoryTest extends \Myname\Myapptests\TestCase
{
/**
* #test
*/
public function test_can_update()
{
$personMock = Mockery::mock(PersonModel::class)
->shouldReceive('fill')
->shouldReceive('save')
->andReturn(true);
$this->app->instance(PersonModel::class, $personMock);
$personRepoMock = Mockery::mock(PersonRepository::class)
->shouldReceive('fetchOrNewPersonById')->andReturn($personMock)
->getMock();
$this->app->bind(ContractRepositoryInterface::class, function () use ($contractRepoMock) {
return $contractRepoMock;
});
$modelMock = Mockery::mock(Contact::class)
$service = new class($modelMock) extends ContactRepository {};
$service->updateContacts([
['person_id' => 3, 'address' => ' XXXXXX update address'],
['person_id' => null, 'address' => ' XXXXXX create address'],
]);
$this->assertTrue(true);
}
}
Obviously I am missing something. Other examples explicitly inject the mocked object into the class they are then testing. Laravels IoC is (should be) doing this for me. Do I have to bind anything?
models structure it looks like the following
class Attribute extends Model
{
public function products()
{
return $this->belongsToMany(Product::class);
}
public function attribute_options()
{
return $this->hasMany(AttributeOption::class);
}
}
class AttributeOption extends Model
{
public function attribute_option()
{
return $this->hasMany(CombinationDetail::class);
}
public function attribute(){
return $this->belongsTo(Attribute::class);
}
}
class Combination extends Model
{
public function combination_details()
{
return $this->hasMany(CombinationDetail::class);
}
}
class CombinationDetail extends Model
{
protected $fillable = ['attribute_options_id'];
public function attribute_options()
{
return $this->belongsTo(AttributeOption::class);
}
}
Relationship models like this.
combination table
combination_details table
how can i show this with selectbox or div with javascript
class SomeModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{some_table}}';
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
This method works properly when I call it from controller
SomeModel::model()->getItemByParentId($someVariable)
But now I have 3 very similar to SomeModel models, so I want to put common methods to one class
class CommonModel extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return self::model()->findAll($criteria);
}
}
class FirstModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{first_table}}';
}
}
class SecondModel extends CommonModel
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return '{{second_table}}';
}
}
But get error
The table "CommonModel" for active record class "CommonModel" cannot
be found in the database.
What is wrong?
Try to change:
public function getItemByParentId($parentId)
{
$criteria=new CDbCriteria;
//some criteria
return static::model()->findAll($criteria);
}
I'm working on ZF2 and I have developped my own storage for authentication but I wonder how to add a new persistent variable (session-like).
Look My Auth Storage :
<?php
namespace Application\Model;
use Zend\Authentication\Storage;
use Zend\Authentication\Storage\StorageInterface;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceManager;
use Application\Model\User;
class MyAuthStorage implements Storage\StorageInterface, ServiceManagerAwareInterface
{
protected $storage;
protected $userTable;
protected $resolvedIdentity;
protected $serviceManager;
public function isEmpty() {
[...]
}
public function read() {
[...]
}
public function write($contents) {
[...]
}
public function clear() {
[...]
}
public function getStorage() {
[...]
}
public function setStorage(Storage\StorageInterface $storage) {
[...]
}
public function getUserTable() {
[...]
}
public function getServiceManager() {
[...]
}
public function setServiceManager(ServiceManager $serviceManager) {
[...]
}
}
I would like to add a variable called foo in my storage (my session ?)
I try this, but it doesn't work :
protected $foo;
public function setFoo($value) {
$this->foo= $value;
}
public function getFoo() {
return $this->foo;
}
Any ideas ?
Ok, I found something and it works for me :
I've added these things in my auth storage class
use Zend\Session\Container;
Then,
protected $container;
public function setContainer(Container $container) {
$this->container = $container;
return $this->container;
}
public function getContainer() {
if (!isset($this->container)) {
$this->setContainer(new Container('myauthstorage'));
}
return $this->container;
}
And now I can do in my controller stuff like that :
$container = $this->getServiceLocator()->get('AuthService')->getStorage()->getContainer();
$container->foo = true;
if ($container->foo) {
// Congrats !
}
A good example how to write last login time.
namespace Application\Model;
use Zend\Authentication\Storage;
class AuthStorage extends Storage\Session
{
public function setRememberMe($rememberMe = 0, $time = 1209600)
{
if ($rememberMe == 1) {
$this->session->getManager()->rememberMe($time);
}
}
public function forgetMe()
{
$this->session->getManager()->forgetMe();
}
public function lastLogin()
{
$this->session->{$this->getMember()}->last_login = time();
}
}
Check this tutorial :
http://samsonasik.wordpress.com/2012/10/23/zend-framework-2-create-login-authentication-using-authenticationservice-with-rememberme/
Sounds like your personnal AuthStorage should extends Storage\Session like this :
namespace SanAuth\Model;
use Zend\Authentication\Storage;
class MyAuthStorage extends Storage\Session
{
public function setRememberMe($rememberMe = 0, $time = 1209600)
{
if ($rememberMe == 1) {
$this->session->getManager()->rememberMe($time);
}
}
public function forgetMe()
{
$this->session->getManager()->forgetMe();
}
}