Pass variable into global scope and determine if query output is null Laravel - localization

I've translation models and I want to run Global query scope that determine the current locale and return the corresponding value upon it or fall back into English if the translation doesn't exist in DB.
I've created a global scope for this purpose and its running good without the ability to fall back into English, so some pages crashes since I'm trying to get property of NULL, and I tried passing some value, but inside the builder I can't determine if the query is going to return null.
How may achieve such thing in Laravel?
my code as follows:
trait WhereLanguage {
/**
* Boot the Where Language trait for a model.
*
* #return void
*/
public static function bootWhereLanguage()
{
static::addGlobalScope(new WhereLanguageScope);
}
}
and the Scope file:
class WhereLanguageScope implements ScopeInterface {
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
*/
public function apply(Builder $builder, Model $model)
{
$this->addWhereLang($builder);
}
/**
* Remove the scope from the given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
*
* #return void
*/
public function remove(Builder $builder, Model $model)
{
$query = $builder->getQuery();
foreach ((array) $query->wheres as $key => $where)
{
// If the where clause is a soft delete date constraint, we will remove it from
// the query and reset the keys on the wheres. This allows this developer to
// include deleted model in a relationship result set that is lazy loaded.
if ($where['column'] == 'lang_id')
{
unset($query->wheres[$key]);
$query->wheres = array_values($query->wheres);
}
}
}
/**
* Extend Builder with custom method.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
*
*/
protected function addWhereLang(Builder $builder)
{
$builder->macro('whereLang', function(Builder $builder)
{
// here 1 is ID for English,
// 48 Arabic, 17 Netherlands...etc
// and It was the App:currentlocale() passed into Language model to determine the ID of current locale.
// but for testing now I hard coded it with ID of 48
$builder->where('lang_id','=','48');
return $builder;
});
}
}
Usage example:
$title = $centre->translations()->whereLang()->first()->name;
Where Centre is my model without localization, and translation is the name of method that handling the relation between Centre & CentreTranslation.
btw I don't want to pass variable obligately.

Related

How to redefine CalculatedPrice in Shopware6?

I'm trying to write plugin in Shopware6, it must add some custom values (like deposit) to Product line item. So I wrote my class
class DepositCalculatedPrice extends CalculatedPrice
{
/** #var float $deposit */
protected $deposit;
public function __construct(
float $unitPrice,
float $totalPrice,
CalculatedTaxCollection $calculatedTaxes,
CalculatedTaxCollection $calculatedTaxesNoDeposit,
TaxRuleCollection $taxRules,
int $quantity = 1,
?ReferencePrice $referencePrice = null,
?ListPrice $listPrice = null,
float $deposit = 0,
) {
parent::__construct(
$unitPrice,
$totalPrice,
$calculatedTaxes,
$taxRules,
$quantity,
$referencePrice,
$listPrice
);
$this->deposit = $deposit;
}
public function getDeposit(): float
{
return FloatComparator::cast($this->deposit);
}
}
Then I use it in my Calculator and then in my PriceProcessor. All goes well until I try to submit my order, but then Shopware6 checks field definintion classes in Checkout/Order/Aggregate/OrderLineItem/OrderLineItemDefinition.php, and it checks Price json field against CalculatedPrice, not DepositCalculatedPrice.
So is there any way to resolve it? Maybe I can use somewhere some descendant of OrderLineItemDefinition.php? Or make it not checking field definitions?
I think you need to follow that document https://docs.shopware.com/en/shopware-platform-dev-en/how-to/cart-change-price
I also need to implement custom price applying from an external system, and i exactly did it according to that documentation, so you need to set exactly the price during cart processing, you can do it using your DepositCalculatedPrice value.

Zend 2 Hydrator Strategy restricting keys

I've been playing with the Zend Hydrator class today and just found the Naming strategies for converting the input keys on the fly. But when playing with the MapNamingStrategy in conjunction with the ObjectProperty hydrator, it seems to add properties that didn't initially exist in the object if the input array contained them.
Is there any way to restrict it from adding new properties and only populating/hydrating existing ones in the input object?
Still no response on this - what I ended up doing was using one of two scenarios but it is still not ideal. The first is to use Class Reflection myself to get a list of keys that are accessible or to search for standard name accessors for same. (this, of course, would not find magic method accessors)
The second was to pre-define a map that didn't only include mismatched key->property mappings but also included all the one-to-one (matched) key->property mappings then filter the input using PHP's array functions prior to running the hydration using the map's key/value pairs. But this kind of defeats the purpose of using hydration as by that point in time, I may as well have used a foreach loop instead. And it eliminates any ability to use abstract destinations in that you have to know all potential input/output key->property relationships in advance.
I ended up doing my own implementation of the first method (again, that will not necessarily handle magic method accessors) which looks for public properties and/or public accessors fitting the standard camel-cased setPropertyName()/getPropertyName() accessor methods.:
<?php
/**
* simple object hydrator using class reflection to find publicly accessible properties and/or methods
*
* Created by PhpStorm.
* User: scottw
* Date: 12/12/16
* Time: 12:06 PM
*/
namespace Finao\Util;
class SimpleHydrator
{
/**
* whether to reset the keyMap following each hydration to clear the hydrator for other data/object pairs
*
* #var bool $resetMap
*/
private static $resetMap = true;
/**
* associative array of key mappings between incoming data and object property names/accessors
* #var array $keyMap
*/
private static $keyMap = array();
public static function setKeyMap($map) {
if(self::is_assoc($map))
static::$keyMap = $map;
}
public static function populateObject(&$targetObject, $dataArray)
{
if (self::is_assoc($dataArray) && is_object($targetObject)) {
// step through array elements and see if there are matching properties or methods
try {
foreach ($dataArray as $k => $v) {
$key = $k;
if(self::is_assoc(static::$keyMap) && array_key_exists($k))
$key = static::$keyMap[$k];
// if original value contains an object, try populating it if the associated value is also array
$origVal = self::getObjectPropertyValue($targetObject, $key);
if (is_object($origVal) && self::is_assoc($v)) {
self::populateObject($origVal, $v);
$v = $origVal;
}
$accessor = 'set' . ucfirst($key);
if (in_array($key, self::getObjectPublicProperties($targetObject)))
$targetObject->$key = $v;
elseif (in_array($accessor, self::getObjectPublicMethods($targetObject)))
$targetObject->$accessor($v);
}
} catch (\Exception $d) {
// do something with failures
}
if(static::$resetMap) static::$keyMap = array();
}
return $targetObject;
}
public static function getObjectPropertyValue($object, $property)
{
$objectReflection = new \ReflectionClass($object);
if ($objectReflection->hasProperty($property) && $objectReflection->getProperty($property)->isPublic())
return $object->$property;
else {
$accessor = 'get' . ucfirst($property);
if ($objectReflection->hasProperty($accessor) && $objectReflection->getMethod($accessor)->isPublic())
return $object->$accessor();
}
}
public static function getObjectPublicProperties($object)
{
if (is_object($object)) {
$publicProperties = array();
$objectReflection = new \ReflectionClass($object);
foreach ($objectReflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $p)
array_push($publicProperties, $p->name);
return $publicProperties;
}
}
public static function getObjectPublicMethods($object)
{
if (is_object($object)) {
$publicMethods = array();
$objectReflection = new \ReflectionClass($object);
foreach ($objectReflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $p)
array_push($publicMethods, $p->name);
return $publicMethods;
}
}
/**
* Determine if a variable is an associative array.
*
* #param mixed Input variable
* #return boolean If the input variable is an associative array.
* #see http://us2.php.net/manual/en/function.is-array.php
*/
public static function is_assoc($array) {
return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
}
}
I eventually added a simple key mapping ability to it. (Note that this has not been rigorously tested and, as the name suggests, is just a simple solution.)

Laravel model scope function names

While creating a scope function with name 'scopeList' in the Model to return a data collection (has select) laravel throws a T_List error. Can I know why?
My code:
namespace project1;
use Illuminate\Database\Eloquent\Model;
class Lookup extends Model
{
protected $fillable = array('type','code','description','listorder');
public $timestamps = false;
/**
* List lookup entries for a given type
*
* #param $type
*
* #return \Illuminate\Support\Collection
*/
public function scopeEntries($query,$type){
return $query->select('code','description')
->where('type',$type)->get();
}
}
If instead of 'scopeEntries', I want to call it 'scopeList' I encounter an error.

Call to a member function get()

I created a sort base module in my ZF2 vendor library. So far everything is working the way I want it to work. I do have a problem. While I am able to extend the base module's controllers, I am unable to access the base service. I am using Doctrine 2 as my database layer.
After implementing the ServiceLocator, I am getting Fatal error: Call to a member function get() on a non-object in my base service file. My BaseService file is shown as below:
namespace MyResource\Service;
use Doctrine\ORM\Mapping as ORM;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class BaseService implements ServiceLocatorAwareInterface
{
/**
* Entity manager instance
*
* #var Doctrine\ORM\EntityManager
*/
protected $_em;
protected $_serviceLocator;
public function __construct()
{
$this->getEntityManager();
}
/**
* Returns an instance of the Doctrine entity manager loaded from the service
* locator
*
* #return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
if (null === $this->_em) {
$this->_em = $this->getServiceLocator()
->get('doctrine.entitymanager.orm_default');
}
return $this->_em;
}
/**
* Set serviceManager instance
*
* #param ServiceLocatorInterface $serviceLocator
* #return void
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
/**
* Retrieve serviceManager instance
*
* #return ServiceLocatorInterface
*/
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
Can anyone help?
Thanks
1):
Your property is called
protected $_serviceLocator;
but you are assigning your values to
protected $serviceLocator;
2)
Are you creating your Service via DI or the service manager? If you do then the ServiceLocator should be automatically injected for you, if you are creating it manually using the "new" keyword then it will not have the ServiceLocatior attached.
There seems to be a glitch in ZF2 .If you try setting the properties
as below the problem will be fixed. Try like this
foreach ($resultSet as $row) {
$entity = new Countrypages();
$entity->setId($row->id);
$entity->setName($row->name);
$entity->setSnippet($row->snippet);
$entity->setSortorder($row->sortorder);
$entity->setActive($row->active);
$entity->setCreated($row->created);
$entity->setModified($row->modified);
$entity->setFirstname($row->firstname);
$entity->setCreatedby($row->createdby);
$entities[] = $entity;
}
ignore this
foreach ($resultSet as $row) {
$entity = new Countrypages();
$entity->setId($row->id);
->setName($row->name);
->setSnippet($row->snippet);
->setSortorder($row->sortorder);
->setActive($row->active);
->setCreated($row->created);
->setModified($row->modified);
->setFirstname($row->firstname);
->setCreatedby($row->createdby);
$entities[] = $entity;
}
I hope this help you save your time.
You're using use use Zend\ServiceManager\ServiceManagerAwareInterface but you're implementing ServiceLocatorAwareInterface (and there's no "use" statement for that one).

How to pass a variable value from one MXML to another MXML?

I am doing a project in Flash Builder using ActionScript.
I have two MXML files: login.mxml and welcome.mxml.
login.mxml:
var username:String="sample";
var password:String="sample";
welcome.mxml:
trace("welcome"+username); // o/p-welcome sample
I have to pass the username value from login.mxml to welcome.xml.
Is it possible to pass a variable value from one MXML to another MXML file? How?
Yes, it is possible. The best way though would be bind the views to an objects values.
Your views don't seem to be to be associated in terms of "one aggregates the other" but their parent (the container view) knows both. So the parent would pass an object reference to both views and when this instance is updated, the views will be notified and and updated via data binding.
If the views are completely independent from each other, it would be the most straight forward way to dispatch events through the application via the application. You should introduce a new event type (i.e. SystemEvent) which is dispatched by the Application. To keep you application clean from too many references to specific global variables used in the views, i'd suggest a delegate if you're to firm with MVC yet:
package de.guj.vila.delegates {
import flash.events.Event;
import flash.events.IEventDispatcher;
import mx.core.FlexGlobals;
import mx.core.IMXMLObject;
import mx.core.UIComponent;
public class ViewDelegate implements IEventDispatcher, IMXMLObject {
//---------------------------------------------------------------------
//
// Properties
//
//---------------------------------------------------------------------
private var _bus:IEventDispatcher;
private var _uiComponent:UIComponent;
/**
* The view which uses the delegate.
*/
public function set uiComponent(value:UIComponent):void {
_uiComponent = value;
}
//---------------------------------------------------------------------
//
// Constructor
//
//---------------------------------------------------------------------
public function ViewDelegate() {
_bus = FlexGlobals.topLevelApplication as IEventDispatcher;
}
//---------------------------------------------------------------------
//
// Implemented Methods
//
//---------------------------------------------------------------------
/**
* #inheritDoc
*
* #see flash.events.IEventDispatcher
*/
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
_bus.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
/**
* #inheritDoc
* #see flash.events.IEventDispatcher
*/
public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
_bus.removeEventListener(type, listener, useCapture);
}
/**
* #inheritDoc
* #see flash.events.IEventDispatcher
*/
public function dispatchEvent(event:Event):Boolean {
return _bus.dispatchEvent(event);
}
/**
* #inheritDoc
*
* #see flash.events.IEventDispatcher
*/
public function hasEventListener(type:String):Boolean {
return _bus.hasEventListener(type);
}
/**
* #inheritDoc
*
* #see mx.core.IMXMLObject
*/
public function initialized(document:Object, id:String):void {
uiComponent = document as UIComponent;
}
/**
* #inheritDoc
*
* #see flash.events.IEventDispatcher
*/
public function willTrigger(type:String):Boolean {
return _bus.willTrigger(type);
}
}
}
You can just stuff the in the fx:Declarations block, give it an id and dispatch events from view to view. You just have to set up the listeners. This way you can easily implement quite a clean structure, since you just have to refactor the delegate. Utilizing the delegate as a base class, you can event handle any events in the delegate, so you views stay clean and, most importantly, it's easy to port to a different MVC approach, because you already isolated view behaviour from the applications behaviour.
In the end you'll want to use an MVC framework (RobotLegs for example) to be able to scale your application easily.

Resources