CakePHP 3 good practice - cakephp-3.0

I'm doing some logic code in my entities and i don't know if it's a good practice. I got an object it belongs to a place. My PlacesTable works with treeBehavior and i want to know the place of an object but also the city where is the place:
I'm doing this and i want to know if it's a good practice:
class Object extends Entity
{
protected $_accessible = [
'*' => true,
'city' => true
];
public function _getCity()
{
$Places = TableRegistry::get('Zones');
$cityId = $Places->getRoot($this->place);
return $Places->get($cityId);
}
}
Then my virtual field city is now a CityEntity

Related

Yii2 multilingual slug and language switcher that will "respect" translated slug's

The problem is - I can't figure out how to switch to translated slug:
I've implemented multilingual slugs using lav45/yii2-translated-behavior.
Database is quite simple:
Portfolio model:
id | created_at | is_active
PortfolioLang model:
portfolio_id | lang_id | title | content
So far - so good. I have a actionView that calls out translated content as follows:
protected function findModelBySlug($slug)
{
if (($model = Portfolio::findOne(['slug' => $slug])) !== null) {
return $model;
} else {
throw new NotFoundHttpException();
}
}
public function actionView($_lang, $slug)
{
$portfolioLang = PortfolioLang::findOne(['lang_id' => $_lang,'slug' => $slug]);
$model = $portfolioLang->portfolio;
$pictures = PortfolioPicture::find()->where(['portfolio_id' => $model->id])->orderBy(['sorting'=>SORT_ASC])->all();
return $this->render('view', [
'model' => $model,
'picture' => $pictures,
'langList' => Lang::getList(),
]);
}
Must note, that this is working, "until" it try to switch between languages while I'm opened the entry.
I was using example code from here: https://github.com/lav45/yii2-translated-behavior-demo/blob/master/frontend/components/LangHelper.php
I guess that I need something else than a sample code (it looks like it works only for current ID's for existing entries). Could you, someone, give me some hints for the next step?
Thanks in advance!

Return URL image in Laravel API

I need to return URL path and name image from database.
This my call method to get data from database:
public function index(){
$rav=Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse($rav->toArray(),'rav show is succesfuly');
}
Output data it look like this:
{
"id": 88,
"image": "1579781806.png",
"nameravs": "asdad"
},
But I want to return image with path URL like this:
"image": http://127.0.0.1:8000/images_ravs/1579781806.png
You can use Eloquent Accessor
add the image url attribute in Rav.php Model like below. then you can access it any place.
public function getImageUrlAttribute($value)
{
return env('APP_URL'). '/images_ravs/' . $this->image;
}
And don't forget to Add Appends property inside the Model
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = ['image_url'];
then you can access it like below.
$rav->image_url
Define An Accessor in your model like this example :
public function getImageAttribute($value)
{
return env('APP_URL') . Storage::url($value);
}
Try this:
public function index(){
$rav = Rav::select('id','image','nameravs')->get('image');
return $this->sendResponse(
[
'id' => $rav->id,
'image' => URL::to('/').'/images_ravs/'.rav->image,
'nameravs' => $rev->nameravs
],'rav show is succesfuly');
}
You can use selectRaw or select with DB::raw and just concat that path as a prepended string infront of your image column in your query:
Rav::select(DB::raw("id, nameravs, CONCAT('/images_ravs/', image) as image"))->get()->toArray();
No need to include the URL (unless for some reason you have some type of CDN in front of it) in which case you can just escape the string and add it if necessary.
I would do something like this: Try to use as many od Laravel's built-in functions as possible. In most cases you don't need to reinvent the wheel.
public function index(){
$ravs = Rav::select('id','image','nameravs')->get();
$results = [];
foreach($ravs as $rav){
$rav->image = env('APP_URL') . '/images_ravs/' . $rav->image;
array_push($results, $rav);
}
return response()->json($results);
}
In the Model you can create getAttribute:
public function getImageAttribute()
{
return $this->attributes['image'] ? URL::to('/uploads/' . $this->attributes['image']) : null;
}
Or you can create custom casts file:
protected $casts = [
'image' => ImageCast::class,
'created_at' => 'datetime',
'updated_at' => 'datetime',
];

I can't get the data in appends with json in Laravel

I have two models in laravel project Item and ItemImgs
Item.php
class Item extends Model
{
protected $appends = [
'photo',
];
public function imgs()
{
return $this->hasMany(ItemImage::class);
}
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img.src;
}
}
it's worked in views
dd(Item::all()); //worked
{{ $cane->photo}}; //worked
but when I try to get json
return response()->json([
'items' => Item::with('imgs')->get(),
]);
// not worked. Got timeout 500
You cannot use dot notation in PHP.
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img.src; // Dot notation is not allowed
}
but you've to use:
public function getPhotoAttribute()
{
$img = $this->imgs->first();
return $img->src;
}
if what you're trying to do is to get the items that have imgs() then what you should do is query by relationship existence, as mentioned in the docs
https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence
'items' => Item::has('imgs')->get()
It is not possible to refer to the linked model tables in attributes. It works in views but gives out a memory error when outputting an array through json.
public function getPhotoAttribute(){
$img = ItemImage::where('item', $this->id)-
>first();
}
It works that way, but it's not elegant.

Add new attribute dynamically to the existing model object in Yii2 framework

In Yii2 framework is it possible to add a new attribute dynamically to an existing object, which is retrieved from Database?
Example
//Retrieve from $result
$result = Result::findone(1);
//Add dynamic attribute to the object say 'result'
$result->attributes = array('attempt' => 1);
If it is not possible, please suggest an alternate best method to implement it.
Finally I would be converting the result to a json object. In my application, at the behaviour code block, I have used like this:
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
You can add define a public variable inside your model, that will store dynamic attributes as associative array. It'll look something like this:
class Result extends \yii\db\ActiveRecord implements Arrayable
{
public $dynamic;
// Implementation of Arrayable fields() method, for JSON
public function fields()
{
return [
'id' => 'id',
'created_at' => 'created_at',
// other attributes...
'dynamic' => 'dynamic',
];
}
...
..in your action pass some dynamic values to your model, and return everything as JSON:
public function actionJson()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = Result::findOne(1);
$model->dynamic = [
'field1' => 'value1',
'field2' => 2,
'field3' => 3.33,
];
return $model;
}
In result you will get JSON like this:
{"id":1,"created_at":1499497557,"dynamic":{"field1":"value1","field2":2,"field3":3.33}}

Can I have a ZF3 MVC Framework Controller with parameters in the constructor?

I have a Zend Framework 3 MVC app with a controller with two end points. Both need to access the same class. It seems like the best way to do this would be to would be to make an instance of this class a property of the controller class like this:
class IndexController extends AbstractActionController
{
/**
* var Utility $utility
*/
protected $utility;
public function __construct(Utility $utility)
{
$this->utility = $utility;
}
public function indexAction()
{
$this->utility->doA('param1');
return new ViewModel();
}
public function otherAction()
{
$results = $this->utility->validateRequest($this->request);
if ($results)
{
return new ViewModel();
}
else
{
throw new Exception('Invalid request');
}
}
}
However, I don't know how to pass paramaters to the constructor since I don't know where Zend Framework "makes" it.
Zend Framework uses a concept called Dependency Injection. This is based on the D in SOLID, dependency inversion. Theory aside, you need to make a custom factory for your controller in modules.config.php. You also need to make a factory for the class calld Utility.
So first of all, you probably made your project with a command similar to composer create-project -sdev zendframework/skeleton-application. If you did that you probably don't have the latest version of Service Manager. See if the file vendor/bin/generate-factory-for-class exists. If not, execute composer update zendframework/zend-servicemanager to add it there.
Now lets make a factory for the utility class. Lets assume its in module/Application/src/Service/Utility.php and has the namespace Application\Service. You just type vendor/bin/generate-factory-for-class Application\\Service\\Utility > module/Application/src/Service/UtilityFactory.php. If you look in that file you can see:
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new Utility();
}
Now lets do the same for the controller with vendor/bin/generate-factory-for-class Application\\Controller\\IndexController > module/Application/src/Controller/IndexControllerFactory.php. Open this factory and see its a little more complex.
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new IndexController($container->get(\Application\Service\Utility::class));
}
$container is your dependency injection container. It executes the __invoke command in these factories when called.
One more thing left to do. you need to edit your module.config.php. Replace the line
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class,
],
],
with
'controllers' => [
'factories' => [
Controller\IndexController::class => Controller\IndexControllerFactory::class,
],
],
Now add the following section to the config:
'service_manager' => [
'factories' => [
Service\Utility::class => InvokableFactory::class,
],
],
Then your controller should work.