সিমফনি ২.০ এজেএক্স অ্যাপ্লিকেশনে জেএসএনে মতবাদ সত্তাগুলি কীভাবে এনকোড করা যায়?


91

আমি গেম অ্যাপটি বিকাশ করছি এবং সিমফনি ২.০ ব্যবহার করছি। আমার ব্যাকএন্ডে অনেক এজেএক্স অনুরোধ রয়েছে। এবং আরও প্রতিক্রিয়াগুলি সত্তাকে জেএসএনে রূপান্তর করছে। উদাহরণ স্বরূপ:

class DefaultController extends Controller
{           
    public function launchAction()
    {   
        $user = $this->getDoctrine()
                     ->getRepository('UserBundle:User')                
                     ->find($id);

        // encode user to json format
        $userDataAsJson = $this->encodeUserDataToJson($user);
        return array(
            'userDataAsJson' => $userDataAsJson
        );            
    }

    private function encodeUserDataToJson(User $user)
    {
        $userData = array(
            'id' => $user->getId(),
            'profile' => array(
                'nickname' => $user->getProfile()->getNickname()
            )
        );

        $jsonEncoder = new JsonEncoder();        
        return $jsonEncoder->encode($userData, $format = 'json');
    }
}

এবং আমার সমস্ত কন্ট্রোলার একই কাজ করে: একটি সত্তা পান এবং এর কিছু ক্ষেত্র JSON এ এনকোড করুন। আমি জানি যে আমি নরমালাইজার ব্যবহার করতে পারি এবং সমস্ত অধিকার এনকোড করতে পারি। কিন্তু যদি কোনও সত্তা অন্য সত্তার সাথে চক্রযুক্ত লিঙ্ক করে থাকে? নাকি সত্ত্বার গ্রাফ খুব বড়? তোমার কি কোন মতামত আছে?

সত্তার জন্য কিছু এনকোডিং স্কিমা ... বা NormalizableInterfaceসাইকেল চালনা এড়ানোর জন্য ব্যবহার সম্পর্কে আমি মনে করি ..,

উত্তর:


83

আর একটি বিকল্প হ'ল জেএমএসএসিরাইজারবান্ডেল ব্যবহার করা । আপনার নিয়ামক আপনি তারপর না

$serializer = $this->container->get('serializer');
$reports = $serializer->serialize($doctrineobject, 'json');
return new Response($reports); // should be $reports as $doctrineobject is not serialized

সত্তা শ্রেণিতে টীকাগুলি ব্যবহার করে কীভাবে সিরিয়ালাইজেশন করা হয় তা আপনি কনফিগার করতে পারেন। উপরের লিঙ্কে ডকুমেন্টেশন দেখুন। উদাহরণস্বরূপ, আপনি এখানে লিঙ্কযুক্ত সত্তাগুলি কীভাবে বাদ দেবেন তা এখানে:

 /**
* Iddp\RorBundle\Entity\Report
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Iddp\RorBundle\Entity\ReportRepository")
* @ExclusionPolicy("None")
*/
....
/**
* @ORM\ManyToOne(targetEntity="Client", inversedBy="reports")
* @ORM\JoinColumn(name="client_id", referencedColumnName="id")
* @Exclude
*/
protected $client;

7
আপনাকে জেএমএস \ সিরিয়ালাইজারবান্ডেল; টিকা \ এক্সক্লুশনপলিসি ব্যবহার যুক্ত করতে হবে; জেএমএস \ সিরিয়ালাইজারবান্ডেল \ টিকা; বাদ দিন; আপনার সত্তায় এবং জেএমএসআরসিয়ারাইজার বান্ডেল ইনস্টল করুন এটির কাজ করার জন্য
ioleo

4
আপনি যদি এটিকে পরিবর্তন করেন তবে দুর্দান্ত কাজ করে: নতুন প্রতিক্রিয়া ফিরিয়ে দিন ($ প্রতিবেদনগুলি);
গ্রেওয়াইয়ার

7
যেহেতু টীকাগুলি বান্ডিলের বাইরে চলে গেছে, সঠিক ব্যবহারের বিবৃতি এখন: জেএমএস \ সিরিয়ালাইজার not টীকা জেএমএস ব্যবহার করুন \ সিরিয়ালাইজার not টিকা \ বাদ দিন;
পিয়র-লুক জেনড্রেউ

4
ডক্ট্রাইনের জন্য ডকুমেন্টেশন বলে যে অবজেক্টগুলি সিরিয়ালাইজ করা বা দুর্দান্ত যত্নের সাথে সিরিয়ালাইজ করা না।
ব্লুবারন

এমনকি জেএমএসএসিয়ালাইজারবান্ডেল ইনস্টল করার দরকার নেই। আপনার কোড জেএমএসএসেরাইজারবান্ডেল প্রয়োজন ছাড়াই কাজ করেছে।
ডার্ক জান স্পিলম্যান

149

পিএইচপি 5.4 দিয়ে এখন আপনি এটি করতে পারেন:

use JsonSerializable;

/**
* @Entity(repositoryClass="App\Entity\User")
* @Table(name="user")
*/
class MyUserEntity implements JsonSerializable
{
    /** @Column(length=50) */
    private $name;

    /** @Column(length=50) */
    private $login;

    public function jsonSerialize()
    {
        return array(
            'name' => $this->name,
            'login'=> $this->login,
        );
    }
}

এবং তারপর কল

json_encode(MyUserEntity);

4
আমি এই সমাধানটি খুব পছন্দ করি!
মাইকেল 14

4
আপনি যদি অন্য বান্ডিলের উপর নির্ভরশীলতা সর্বনিম্ন রাখার চেষ্টা করছেন তবে এটি দুর্দান্ত সমাধান ...
ড্রামজো

4
সংযুক্ত সত্তা সম্পর্কে কি?
জন দি রিপার

7
এটি সত্তা সংগ্রহের সাথে কাজ করে বলে মনে হচ্ছে না (যেমন: OneToManyসম্পর্ক)
পিয়েরে লেস্পিনে

4
এটি একক দায়িত্বের নীতি লঙ্ঘন করে এবং যদি আপনার সত্ত্বা মতবাদ দ্বারা স্বয়ংক্রিয়ভাবে উত্পন্ন হয়
জিম স্মিথ

39

আপনি নিজের জটিল সত্তা জসন-এ স্বয়ংক্রিয়ভাবে এনকোড করতে পারেন:

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;

$serializer = new Serializer(array(new GetSetMethodNormalizer()), array('json' => new 
JsonEncoder()));
$json = $serializer->serialize($entity, 'json');

4
ধন্যবাদ, তবে আমার কাছে প্লেয়ার সত্তা রয়েছে যার গেম সত্ত্বা সংগ্রহের সাথে লিঙ্ক রয়েছে এবং প্রতিটি গেম সত্তায় এটি খেলোয়াড়দের সাথে লিঙ্ক রয়েছে। এটার মতো কিছু. এবং আপনি কী ভাবেন যে গেটসেটমথডনর্মালাইজার সঠিকভাবে কাজ করবে (এটি পুনরাবৃত্ত আলগোরিদম ব্যবহার করে)?
Dmytro ক্রাসুন

4
হ্যাঁ এটি পুনরাবৃত্ত এবং এটি আমার ক্ষেত্রে আমার সমস্যা ছিল। সুতরাং, নির্দিষ্ট সত্তাগুলির জন্য, আপনি কাস্টমনরমালাইজার এবং এর নরমালাইজেবল ইন্টারফেস ব্যবহার করতে পারেন যেমন আপনি জানেন।
ওয়েবডাএল

4
যখন আমি এটি চেষ্টা করেছি তখন আমি "মারাত্মক ত্রুটি: 134217728 বাইটের অনুমোদিত মেমরি সাইজটি / হোমে / জেসন / প্রেসারবক্স / ভেন্ডার / সাইমফনি / এসআরসি / সিমফনি / কম্পোনেন্ট / সরাইজার / নরমালাইজার / গেটসেটমেথডনর্মালাইজার.এফপি চালু লাইন 44 "। আমি ভাবছি কেন?
জেসন সোয়েট

4
যখন আমি চেষ্টা করেছি আমি ব্যতিক্রমের নীচে পেয়েছি .. মারাত্মক ত্রুটি: '100' সর্বাধিক ফাংশন নেস্টিং স্তর পৌঁছেছে, বাতিল করা হচ্ছে! সি তে: \ wamp \ www \ myapp \ অ্যাপ্লিকেশন \ গ্রন্থাগারগুলি \ মতবাদ \ সিমফনি \ উপাদান \ সিরিয়ালাইজার \ নরমালাইজার \ 22S লাইনটিতে
getSetMethodNormalizer.php

4
@ user2350626 দেখুন stackoverflow.com/questions/4293775/...
webda2l

11

উত্তরটি সম্পূর্ণ করতে: সিমফনি 2 json_encode এর চারপাশে একটি মোড়কের সাথে আসে: সিমফনি / উপাদান / এইচটিপিফাউন্ডেশন / জসনরেস্পোনস

আপনার নিয়ন্ত্রণকারীগুলিতে সাধারণ ব্যবহার:

...
use Symfony\Component\HttpFoundation\JsonResponse;
...
public function acmeAction() {
...
return new JsonResponse($array);
}

আশাকরি এটা সাহায্য করবে

জে


10

সারণীকরণের সত্তাগুলির সমস্যার সমাধান আমি নিম্নলিখিত হিসাবে পেয়েছি:

#config/config.yml

services:
    serializer.method:
        class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
    serializer.encoder.json:
        class: Symfony\Component\Serializer\Encoder\JsonEncoder
    serializer:
        class: Symfony\Component\Serializer\Serializer
        arguments:
            - [@serializer.method]
            - {json: @serializer.encoder.json }

আমার নিয়ামক:

$serializer = $this->get('serializer');

$entity = $this->get('doctrine')
               ->getRepository('myBundle:Entity')
               ->findOneBy($params);


$collection = $this->get('doctrine')
               ->getRepository('myBundle:Entity')
               ->findBy($params);

$toEncode = array(
    'response' => array(
        'entity' => $serializer->normalize($entity),
        'entities' => $serializer->normalize($collection)
    ),
);

return new Response(json_encode($toEncode));

অন্য উদাহরণ:

$serializer = $this->get('serializer');

$collection = $this->get('doctrine')
               ->getRepository('myBundle:Entity')
               ->findBy($params);

$json = $serializer->serialize($collection, 'json');

return new Response($json);

এমনকি আপনি এটি http://api.symfony.com/2.0 এ অ্যারে ডিজিটালাইজ করতে কনফিগার করতে পারেন



6

আমাকে কেবল একই সমস্যাটি সমাধান করতে হয়েছিল: জসন-এনকোডিং একটি সত্তা ("ব্যবহারকারী") এর সাথে অন্য সত্তার ("অবস্থান") এর সাথে একাধিক দ্বিদীপ্ত অ্যাসোসিয়েশন রয়েছে।

আমি বেশ কয়েকটি জিনিস চেষ্টা করেছিলাম এবং আমি মনে করি এখন আমি সেরা গ্রহণযোগ্য সমাধান খুঁজে পেয়েছি। ডেভিড দ্বারা লিখিত হিসাবে একই কোড ব্যবহার করার ধারণাটি ছিল, তবে কোনওরকালে নরমালাইজারকে থামিয়ে দেওয়ার জন্য অসীম পুনরাবৃত্তিটি বিরত রাখুন।

আমি কোনও কাস্টম নরমালাইজার প্রয়োগ করতে চাইনি, কারণ এই গেটসেটমথডনরমালাইজারটি আমার মতে (প্রতিফলন ইত্যাদির উপর ভিত্তি করে) একটি দুর্দান্ত পদ্ধতি। সুতরাং আমি এটিকে সাবক্লাস করার সিদ্ধান্ত নিয়েছি, যা প্রথম দর্শনে তুচ্ছ নয়, কারণ কোনও সম্পত্তি (আইজমেটমোথ) অন্তর্ভুক্ত করা উচিত কিনা তা বলার পদ্ধতিটি ব্যক্তিগত বলে কারণ।

তবে, কেউ স্বাভাবিককরণের পদ্ধতিটিকে ওভাররাইড করতে পারে, সুতরাং আমি "পয়েন্ট" উল্লেখ করে এমন সম্পত্তিটি অনিষ্ট করে কেবল এই মুহূর্তে বাধা দিয়েছিলাম - তাই অনির্দিষ্ট লুপটি ব্যাহত হয়।

কোডে এটি দেখতে এরকম দেখাচ্ছে:

class GetSetMethodNormalizer extends \Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer {

    public function normalize($object, $format = null)
    {
        // if the object is a User, unset location for normalization, without touching the original object
        if($object instanceof \Leonex\MoveBundle\Entity\User) {
            $object = clone $object;
            $object->setLocations(new \Doctrine\Common\Collections\ArrayCollection());
        }

        return parent::normalize($object, $format);
    }

} 

4
আমি আশ্চর্য হয়েছি যে এটি সাধারণকরণ করা কতটা সহজ হতে পারে, যাতে ১ টির জন্য কখনই সত্তা ক্লাস স্পর্শ করার দরকার পড়ে না, ২. শুধু "অবস্থানগুলি" ফাঁকা নয়, প্রতিটি সংগ্রহ টাইপ ক্ষেত্র যা অন্যান্য এন্টিমেটে সম্ভাব্য ম্যাপ করে। অর্থাৎ এটির ক্রমিকায়নের জন্য এন্টের কোনও অভ্যন্তরীণ / অগ্রিম জ্ঞানের প্রয়োজন নেই, পুনরাবৃত্তি মুক্ত।
মার্কোস

6

আমারও একই সমস্যা ছিল এবং আমি আমার নিজস্ব এনকোডার তৈরি করার সিদ্ধান্ত নিয়েছিলাম, যা তারা নিজেরাই পুনরাবৃত্তি সহ্য করবে।

আমি ক্লাস তৈরি করেছি যা প্রয়োগ করে Symfony\Component\Serializer\Normalizer\NormalizerInterfaceএবং একটি পরিষেবা যা প্রত্যেককে ধারণ করে NormalizerInterface

#This is the NormalizerService

class NormalizerService 
{

   //normalizer are stored in private properties
   private $entityOneNormalizer;
   private $entityTwoNormalizer;

   public function getEntityOneNormalizer()
   {
    //Normalizer are created only if needed
    if ($this->entityOneNormalizer == null)
        $this->entityOneNormalizer = new EntityOneNormalizer($this); //every normalizer keep a reference to this service

    return $this->entityOneNormalizer;
   }

   //create a function for each normalizer



  //the serializer service will also serialize the entities 
  //(i found it easier, but you don't really need it)
   public function serialize($objects, $format)
   {
     $serializer = new Serializer(
            array(
                $this->getEntityOneNormalizer(),
                $this->getEntityTwoNormalizer()
            ),
            array($format => $encoder) );

     return $serializer->serialize($response, $format);
}

একটি সাধারণকরণের উদাহরণ:

use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class PlaceNormalizer implements NormalizerInterface {

private $normalizerService;

public function __construct($normalizerService)
{
    $this->service = normalizerService;

}

public function normalize($object, $format = null) {
    $entityTwo = $object->getEntityTwo();
    $entityTwoNormalizer = $this->service->getEntityTwoNormalizer();

    return array(
        'param' => object->getParam(),
        //repeat for every parameter
        //!!!! this is where the entityOneNormalizer dealt with recursivity
        'entityTwo' => $entityTwoNormalizer->normalize($entityTwo, $format.'_without_any_entity_one') //the 'format' parameter is adapted for ignoring entity one - this may be done with different ways (a specific method, etc.)
    );
}

}

একটি নিয়ামক মধ্যে:

$normalizerService = $this->get('normalizer.service'); //you will have to configure services.yml
$json = $normalizerService->serialize($myobject, 'json');
return new Response($json);

সম্পূর্ণ কোডটি এখানে: https://github.com/progracqteur/WikiPedale/tree/master/src/Progracqteur/WikipedaleBundle/Res উত্স / নরমালাইজার


6

সিমফোনিতে ২.৩

/app/config/config.yml

framework:
    # сервис конвертирования объектов в массивы, json, xml и обратно
    serializer:
        enabled: true

services:
    object_normalizer:
        class: Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer
        tags:
        # помечаем к чему относится этот сервис, это оч. важно, т.к. иначе работать не будет
          - { name: serializer.normalizer }

এবং আপনার নিয়ামকের জন্য উদাহরণ:

/**
 * Поиск сущности по ИД объекта и ИД языка
 * @Route("/search/", name="orgunitSearch")
 */
public function orgunitSearchAction()
{
    $array = $this->get('request')->query->all();

    $entity = $this->getDoctrine()
        ->getRepository('IntranetOrgunitBundle:Orgunit')
        ->findOneBy($array);

    $serializer = $this->get('serializer');
    //$json = $serializer->serialize($entity, 'json');
    $array = $serializer->normalize($entity);

    return new JsonResponse( $array );
}

তবে ক্ষেত্র টাইপের \ ডেটটাইম নিয়ে সমস্যাগুলি থেকে যাবে।


6

এটি আরও একটি আপডেট (সিমফনি ভি: ২.7+ এবং জেএমএসরিশালাইজার ভি: ০.০৩। * @ দেব) এর জন্য , যাতে জেমস পুরো অবজেক্ট গ্রাফটি লোড করার ও সিরিয়াল করার চেষ্টা করে (বা চক্রীয় সম্পর্কের ক্ষেত্রে ..)

মডেল:

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\ExclusionPolicy;  
use JMS\Serializer\Annotation\Exclude;  
use JMS\Serializer\Annotation\MaxDepth; /* <=== Required */
/**
 * User
 *
 * @ORM\Table(name="user_table")
///////////////// OTHER Doctrine proprieties //////////////
 */
 public class User
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected   $id;

    /**
     * @ORM\ManyToOne(targetEntity="FooBundle\Entity\Game")
     * @ORM\JoinColumn(nullable=false)
     * @MaxDepth(1)
     */
    protected $game;
   /*
      Other proprieties ....and Getters ans setters
      ......................
      ......................
   */

ভিতরে একটি ক্রিয়া:

use JMS\Serializer\SerializationContext;
  /* Necessary include to enbale max depth */

  $users = $this
              ->getDoctrine()
              ->getManager()
              ->getRepository("FooBundle:User")
              ->findAll();

  $serializer = $this->container->get('jms_serializer');
  $jsonContent = $serializer
                   ->serialize(
                        $users, 
                        'json', 
                        SerializationContext::create()
                                 ->enableMaxDepthChecks()
                  );

  return new Response($jsonContent);

5

আপনি যদি সিমফনি ২.7 বা তার বেশি ব্যবহার করে থাকেন এবং সিরিয়ালাইজেশনের জন্য কোনও অতিরিক্ত বান্ডিল অন্তর্ভুক্ত করতে না চান তবে সম্ভবত আপনি জসন-তে মতবাদ সত্ত্বা সিলাইজ করার জন্য এই উপায়টি অনুসরণ করতে পারেন -

  1. আমার (কমন, প্যারেন্ট) কন্ট্রোলারে আমার একটি ফাংশন রয়েছে যা সিরিয়ালাইজার প্রস্তুত করে

    use Symfony\Component\Serializer\Encoder\JsonEncoder;
    use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
    use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
    use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
    use Symfony\Component\Serializer\Serializer;
    
    // -----------------------------
    
    /**
     * @return Serializer
     */
    protected function _getSerializer()
    {  
        $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
        $normalizer           = new ObjectNormalizer($classMetadataFactory);
    
        return new Serializer([$normalizer], [new JsonEncoder()]);
    }
    
  2. তারপরে এটি JSON এ সত্তাগুলি সিরিয়াল করতে ব্যবহার করুন

    $this->_getSerializer()->normalize($anEntity, 'json');
    $this->_getSerializer()->normalize($arrayOfEntities, 'json');
    

সম্পন্ন!

তবে আপনার কিছু সূক্ষ্ম সুরের প্রয়োজন হতে পারে। উদাহরণ স্বরূপ -


4

যখন আপনাকে সিমফোনিতে প্রচুর আরএসটি এপিআই এন্ডপয়েন্টস তৈরি করতে হবে, নীচের বান্ডেলগুলির স্ট্যাক ব্যবহার করার সর্বোত্তম উপায়:

  1. মতবাদ সত্তা ক্রমিকায়নের জন্য জেএমএসআরসিয়ারাইজারবান্ডেল
  2. প্রতিক্রিয়া দেখার শ্রোতার জন্য FOSRestBundle বান্ডিল। এছাড়াও এটি নিয়ামক / ক্রিয়া নামের উপর ভিত্তি করে রুটের সংজ্ঞা তৈরি করতে পারে।
  3. অনলাইন ডকুমেন্টেশন এবং স্যান্ডবক্স (যা কোনও বাহ্যিক সরঞ্জাম ছাড়াই শেষ পয়েন্ট পরীক্ষা করতে দেয়) নেলমিওএপিডোকডবান্ডেল auto

আপনি যখন সবকিছু ঠিকঠাকভাবে কনফিগার করেন, তখন আপনার সত্তা কোডটি দেখতে পাবেন:

use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;

/**
 * @ORM\Table(name="company")
 */
class Company
{

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     *
     * @JMS\Expose()
     * @JMS\SerializedName("name")
     * @JMS\Groups({"company_overview"})
     */
    private $name;

    /**
     * @var Campaign[]
     *
     * @ORM\OneToMany(targetEntity="Campaign", mappedBy="company")
     * 
     * @JMS\Expose()
     * @JMS\SerializedName("campaigns")
     * @JMS\Groups({"campaign_overview"})
     */
    private $campaigns;
}

তারপরে, নিয়ামক কোড:

use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use FOS\RestBundle\Controller\Annotations\View;

class CompanyController extends Controller
{

    /**
     * Retrieve all companies
     *
     * @View(serializerGroups={"company_overview"})
     * @ApiDoc()
     *
     * @return Company[]
     */
    public function cgetAction()
    {
        return $this->getDoctrine()->getRepository(Company::class)->findAll();
    }
}

এই ধরনের সেট আপ করার সুবিধাগুলি হ'ল:

  • @ জেএমএস \ সত্তায় প্রকাশিত () টীকাগুলি সাধারণ ক্ষেত্রগুলিতে এবং যে কোনও ধরণের সম্পর্কের ক্ষেত্রে যুক্ত করা যেতে পারে। এছাড়াও কিছু পদ্ধতি প্রয়োগের ফলাফল প্রকাশের সম্ভাবনা রয়েছে (এর জন্য টিকা @ জেএমএস \ ভার্চুয়ালপ্রোপার্টি () ব্যবহার করুন)
  • সিরিয়ালাইজেশন গোষ্ঠীগুলির সাহায্যে আমরা বিভিন্ন পরিস্থিতিতে উন্মুক্ত ক্ষেত্রগুলি নিয়ন্ত্রণ করতে পারি।
  • কন্ট্রোলাররা খুব সাধারণ। অ্যাকশন পদ্ধতি সরাসরি কোনও সত্তা বা সত্ত্বার অ্যারে ফিরিয়ে দিতে পারে এবং সেগুলি স্বয়ংক্রিয়ভাবে সিরিয়ালায়িত হবে।
  • এবং @ এপিডোক () কোনও আরইএসটি ক্লায়েন্ট বা জাভাস্ক্রিপ্ট কোড ছাড়াই সরাসরি ব্রাউজার থেকে শেষ পয়েন্টটি পরীক্ষা করতে দেয়

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.